Microtasks vs Macrotasks (Job Queues)

Predict the Output

Example

Promise callbacks (microtasks / "jobs") always run before the next timer (macrotask), even a 0 ms one.

console.log('1 script start');

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

Promise.resolve()
  .then(() => console.log('3 promise.then (microtask)'))
  .then(() => console.log('4 second then (microtask)'));

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

console.log('2 script end');

Output

1 script start
2 script end
3 promise.then (microtask)
3b queueMicrotask (microtask)
4 second then (microtask)
5 setTimeout (macrotask)

Queues Compared

QueueAlso calledExamplesWhen it runs
Microtask queuejob queuePromise.then/catch/finally, await continuation, queueMicrotask, MutationObserverright after the current task, until empty
Macrotask queuetask / callback queuesetTimeout, setInterval, DOM events, MessageChannel, I/Oone per loop turn
Node onlyprocess.nextTick (before promises), setImmediate (check phase)

async/await Order

Example

Code after await continues as a microtask.

async function task() {
  console.log('B inside async, before await');
  await null;
  console.log('D after await (microtask)');
}
console.log('A start');
task();
setTimeout(() => console.log('E timeout'), 0);
console.log('C end of script');

Output

A start
B inside async, before await
C end of script
D after await (microtask)
E timeout