2 min read

Microtasks vs. Macrotasks

In JavaScript's Event Loop, not all asynchronous tasks are treated equally. They are divided into two queues: the Macrotask Queue (often just called the Task Queue) and the Microtask Queue.

1. The Queues

Macrotasks (Task Queue)

These are "heavy" tasks. The event loop processes them one by one.

  • setTimeout
  • setInterval
  • setImmediate (Node.js)
  • I/O operations
  • UI Rendering
  • Script loading

Microtasks

These are "lightweight" tasks that need to happen immediately after the current operation completes.

  • Promise callbacks (.then, .catch, .finally)
  • queueMicrotask
  • MutationObserver
  • process.nextTick (Node.js - technically has its own higher priority queue, but often grouped here conceptually)

2. The Execution Rule

The Event Loop follows this specific logic:

  1. Execute one Macrotask from the Macrotask Queue (e.g., the initial script).
  2. Execute ALL Microtasks in the Microtask Queue until it is empty.
  3. Update the UI (Rendering).
  4. Repeat.

Crucial Difference:

  • If a Microtask adds another Microtask, the new one is executed in the same cycle. This can block the Event Loop indefinitely if not careful.
  • Macrotasks wait for the next cycle.

3. Code Example

console.log('1. Script Start');

setTimeout(() => {
  console.log('2. setTimeout (Macrotask)');
}, 0);

Promise.resolve()
  .then(() => {
    console.log('3. Promise 1 (Microtask)');
  })
  .then(() => {
    console.log('4. Promise 2 (Microtask)');
  });

queueMicrotask(() => {
    console.log('5. queueMicrotask (Microtask)');
});

console.log('6. Script End');

Output Order

  1. 1. Script Start (Synchronous)
  2. 6. Script End (Synchronous)
  3. 3. Promise 1 (Microtask) (Microtasks run immediately after stack clears)
  4. 5. queueMicrotask (Microtask)
  5. 4. Promise 2 (Microtask) (Chained promise added to microtask queue)
  6. 2. setTimeout (Macrotask) (Runs in the next loop iteration)

programming/javascript/vanilla/event-loop programming/javascript/vanilla/javascript