JavaScript
Event Loop
Asynchronous Programming
Node.js
Concurrency

Understanding the Event Loop

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

markdown
1The Event Loop is a fundamental concept in asynchronous programming, particularly in environments like JavaScript. Understanding the event loop is crucial for mastering non-blocking I/O operations. This article dives into the mechanics of the event loop, providing technical explanations and examples to clarify how it functions.
2
3## What is the Event Loop?
4
5The event loop is a component of the runtime environment that facilitates non-blocking I/O operations by offloading operations to the operating system. It continuously checks if the call stack is empty and, if it is, pushes the next callback function from the event queue onto the call stack for execution. This mechanism ensures that JavaScript remains single-threaded while allowing for asynchronous execution.
6
7## How the Event Loop Works
8
9At the core of the event loop is a simple loop that performs the following steps:
10
111. **Polling**: The event loop polls the message queue for any pending events or messages.
122. **Executing**: If the call stack is empty, the event loop dequeues the first event and pushes its associated callback onto the call stack.
133. **Waiting**: If the stack is not empty, the event loop waits until it becomes available.
144. **Repeating**: The process is repeated as long as the application is running.
15
16By handling operations in this manner, the event loop allows for the registration of asynchronous callbacks that execute once specific conditions or events occur.
17
18## Examples of Event Loop in JavaScript
19
20Let's explore a basic example using JavaScript:
21
22```javascript
23console.log('Start');
24
25setTimeout(() => {
26  console.log('Timeout callback');
27}, 1000);
28
29console.log('End');

Explanation:

  • When this script runs, "Start" is logged to the console immediately.
  • The setTimeout function is then encountered. Rather than blocking execution, it sets a timer and moves the callback associated with it to the event queue after 1000ms.
  • "End" is logged next, as it's part of the synchronous code.
  • After approximately 1000ms, the event loop detects an empty call stack and dequeues the queued callback to log "Timeout callback."

Call Stack, Message Queue, and Event Table

Call Stack

The call stack is a LIFO (Last In, First Out) data structure. It holds the functions to be executed and tracks the point to which each subroutine should return upon completion.

Message Queue (Event Queue)

The message queue is where callback functions are placed in response to events such as setTimeout triggers, XHR events, and DOM events. When the call stack is empty, the event loop processes events from this queue.

Event Table

This is where long-running tasks are moved out of the main thread. These tasks include timers or callbacks. They notify the event queue when a task is complete.

Microtasks and Macrotasks

JavaScript distinguishes between microtasks (also known as jobs) and macrotasks (or tasks):

  • Microtasks: These have a higher priority than macrotasks and include Promises and MutationObserver objects. They are queued in the microtask queue and executed immediately after the current operation completes, before any rendering occurs.
  • Macrotasks: Regular events like setTimeout, setInterval, and I/O events are queued in the macrotask queue.

Example of Microtasks and Macrotasks

javascript
1console.log('Start');
2
3setTimeout(() => {
4  console.log('Macrotask');
5}, 0);
6
7Promise.resolve().then(() => {
8  console.log('Microtask');
9});
10
11console.log('End');

Output:

 
1Start
2End
3Microtask
4Macrotask

Explanation:

  • "Start" and "End" are logged synchronously.
  • A promise resolves, placing the associated callback in the microtask queue.
  • A setTimeout is processed as a macrotask.
  • "Microtask" is processed before "Macrotask" due to microtasks' higher priority.

Summary

The following table summarizes the key concepts of the event loop:

ConceptDescription
Event LoopContinuously executes the message queue when the call stack is empty.
Call StackKeeps track of functions to execute in a LIFO order.
Message QueueStores callbacks for asynchronous events.
MicrotasksHigher-priority tasks processed after the current execution ends.
MacrotasksLower-priority tasks that are processed at each cycle of the event loop.
Asynchronous EventsEvents like setTimeout, promises, and I/O operations.

This understanding of the event loop, along with key components like microtasks and macrotasks, is vital for writing efficient and non-blocking code in JavaScript.

Additional Resources

To dive deeper into the event loop, consider exploring:

  • The MDN Web Docs for detailed browser implementation guides.
  • Node.js documentation for server-side event loop functioning.
  • Event loop simulation tools available in developer browsers for hands-on learning.
 

Course illustration
Course illustration

All Rights Reserved.