Read first

Microtasks are small jobs that must run as soon as the current task finishes, before the next task and before the next paint. They are why promise callbacks run before timers.

What goes in it

  • Promise reactions: .then, .catch, .finally callbacks.
  • The rest of an async function after an await.
  • queueMicrotask(fn).
  • MutationObserver callbacks.

How it works

After each task, the event loop runs microtasks until the queue is empty, including any microtasks that those microtasks add. Only then does it render or take another task.

queueMicrotask(() => {
  console.log('first');
  queueMicrotask(() => console.log('added during the drain'));
});
setTimeout(() => console.log('task'), 0);
// first
// added during the drain
// task

Traps

  • A microtask that keeps scheduling microtasks blocks the page completely: no paint, no input.
  • In Node.js, process.nextTick callbacks have their own queue that runs before promise microtasks.

Check yourself

Leads to

  • async / await: Syntax that lets promise-based code read top to bottom. An async function always returns a promise; await pauses only that function.