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,.finallycallbacks. - The rest of an
asyncfunction after anawait. queueMicrotask(fn).MutationObservercallbacks.
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
// taskTraps
- A microtask that keeps scheduling microtasks blocks the page completely: no paint, no input.
- In Node.js,
process.nextTickcallbacks have their own queue that runs before promise microtasks.
Check yourself
Why does
.thenrun beforesetTimeout(fn, 0)?
.thencallbacks are microtasks, and the microtask queue is emptied right after the current task; the timer callback is a separate task that waits for a later turn.
What happens if microtasks keep adding microtasks forever?
The queue never empties, so the browser never renders or handles input: the page freezes.
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.