Hiprup

What is the difference between microtasks and macrotasks?

Both are queues of asynchronous callbacks, but microtasks have higher priority.

  • Microtasks — Promise callbacks (.then/.catch), queueMicrotask, await continuations. The whole queue drains after each task.

  • Macrotasks — setTimeout, setInterval, events, I/O. Only one runs per event-loop iteration.

Key rule: after any task, all microtasks run before the next macrotask — so a resolved Promise always beats setTimeout(0).

console.log('1: sync');

setTimeout(() => console.log('2: macrotask'), 0);

Promise.resolve()
  .then(() => console.log('3: microtask 1'))
  .then(() => console.log('4: microtask 2'));

queueMicrotask(() => console.log('5: microtask 3'));

console.log('6: sync');

// Output:
// 1: sync
// 6: sync
// 3: microtask 1
// 5: microtask 3
// 4: microtask 2
// 2: macrotask

// Microtask starvation
function starveMacrotasks() {
  Promise.resolve().then(() => {
    console.log('microtask');
    starveMacrotasks(); // Recursive — setTimeout NEVER fires
  });
}
// starveMacrotasks(); setTimeout(() => console.log('never'), 0);

Sync code runs first (1, 6). Then ALL microtasks drain (3, 5, 4) — note that microtask 2 (.then chain) runs before the macrotask even though it was scheduled after.

Only after ALL microtasks are drained does the macrotask (2) run. The starvation example: recursive microtasks prevent setTimeout from ever executing.

The execution order output question is the #1 event loop interview question. Rule: ALL microtasks drain before the next macrotask.

Promise.then = microtask, setTimeout = macrotask. The starvation example shows deep understanding.

What is the difference between microtasks and macrotasks? | Hiprup