JavaScript Event Loop: microtasks and macrotasks

JavaScript Event Loop: microtasks and macrotasks

The JavaScript event loop is a fundamental part of how JavaScript handles asynchronous code execution. It allows JavaScript to perform non-blocking I/O operations despite being single-threaded, by managing the execution of asynchronous code. Understanding the event loop is crucial for mastering JavaScript, especially when dealing with tasks like handling events, promises, and setTimeout calls.

A key concept in the event loop is the distinction between macrotasks and microtasks, which are processed in a specific order.

The Event Loop

At its core, the event loop continuously checks the call stack and task queues to decide which task to execute next.

  1. Call Stack: The stack where JavaScript functions are executed.
  2. Task Queues: There are two main types of task queues:
    • Macrotask Queue (also called Task Queue): Includes tasks like setTimeout, setInterval, and I/O events (such as click events).
    • Microtask Queue: Includes tasks like promises (then, catch, finally), and MutationObserver callbacks.

How the Event Loop Works:

  1. The event loop first checks if there are any microtasks to execute.
  2. If there are, it will process all microtasks in the microtask queue before it processes any macrotasks.
  3. Once the microtask queue is empty, the event loop will take the next task from the macrotask queue and run it.
  4. This cycle repeats indefinitely.

Macrotasks

Macrotasks are larger, higher-level tasks that are executed by the event loop. These include tasks like rendering updates, handling events, or invoking functions passed to setTimeout, setInterval, or the requestAnimationFrame function.

Common Macrotasks:

  • setTimeout()
  • setInterval()
  • Event handlers (clicks, keypresses)
  • I/O tasks (like file reads)
  • requestAnimationFrame()

Macrotask Execution:

  • When a macrotask is scheduled (e.g., through setTimeout), it goes into the macrotask queue.
  • The event loop picks up these tasks one at a time after all microtasks have been executed.

Example of Macrotask (setTimeout):

console.log("Start"); setTimeout(() => { console.log("Macrotask"); }, 0); console.log("End");

Output:

Start End Macrotask

In this example:

  • The first two console.log calls are executed synchronously.
  • The setTimeout call is a macrotask, so it's added to the macrotask queue and executed after the synchronous code finishes.
  • Even though the delay is 0 milliseconds, it still goes to the macrotask queue, meaning it will only be executed after the current call stack is cleared and any microtasks are processed.

Microtasks

Microtasks are smaller tasks that should be executed as soon as possible, before any macrotasks. They are used to handle promises and other small tasks that need to run after the current task but before any rendering or other events are handled.

Common Microtasks:

  • Promise.then(), Promise.catch(), Promise.finally()
  • MutationObserver callbacks

Microtask Execution:

  • When a microtask is scheduled (e.g., by resolving a promise), it goes into the microtask queue.
  • The event loop will process all microtasks in the microtask queue before moving to any macrotasks.

Example of Microtask (Promise):

console.log("Start"); Promise.resolve().then(() => { console.log("Microtask"); }); console.log("End");

Output:

Start End Microtask

In this example:

  • The console.log("Start") and console.log("End") are executed synchronously.
  • The promise resolution (.then) is a microtask, and it is executed immediately after the synchronous code but before any macrotasks, even though the promise was created asynchronously.

Event Loop with Macrotasks and Microtasks

Let's combine macrotasks and microtasks to see how they work in practice:

Example of Event Loop with Macrotasks and Microtasks:

console.log("Start"); setTimeout(() => { console.log("Macrotask 1"); Promise.resolve().then(() => { console.log("Microtask 1"); }); }, 0); setTimeout(() => { console.log("Macrotask 2"); }, 0); Promise.resolve().then(() => { console.log("Microtask 2"); }); console.log("End");

Output:

Start End Microtask 2 Macrotask 1 Microtask 1 Macrotask 2

Explanation of the Output:

  1. The synchronous console.log("Start") and console.log("End") are executed first.
  2. The first setTimeout (macrotask 1) is scheduled to run after 0 milliseconds and goes to the macrotask queue.
  3. The second setTimeout (macrotask 2) is scheduled in the same way, but it also goes to the macrotask queue.
  4. The first Promise.resolve().then() microtask (microtask 2) is added to the microtask queue and executed right after the synchronous code finishes.
  5. After microtasks are finished, macrotask 1 is processed. Within this macrotask, a new microtask (Microtask 1) is scheduled, which is executed before macrotask 2.
  6. Finally, macrotask 2 is executed.

Key Differences Between Macrotasks and Microtasks:

FeatureMacrotasksMicrotasks
QueueMacrotask QueueMicrotask Queue
TypessetTimeout(), setInterval(), events (click, keypress), requestAnimationFrame()Promise.then(), Promise.catch(), MutationObserver
Execution OrderExecuted after all microtasks in the queueExecuted after the current task, before macrotasks
PriorityLower priority (after all microtasks)Higher priority (before macrotasks)

Conclusion

  • Macrotasks are high-level tasks that are processed in the macrotask queue after all the microtasks are executed.
  • Microtasks are lower-level tasks that need to be executed as soon as possible after the current execution context finishes. They are processed in the microtask queue before any macrotasks.
  • The event loop ensures that all microtasks are processed before moving on to any macrotasks, even if they were scheduled later.

Understanding this distinction and how tasks are processed by the event loop is key to mastering asynchronous programming in JavaScript, particularly when dealing with promises, events, and user interactions.

Soeng Souy

Soeng Souy

Website that learns and reads, PHP, Framework Laravel, How to and download Admin template sample source code free.

Post a Comment

CAN FEEDBACK
close