JavaScriptMedium
What is the microtask queue?
By FrontendPro Editorial Team Updated 9/26/2026
#JavaScript
Answer
The event loop has two queues, and the microtask queue is the one with priority. After the currently running script finishes, the engine drains the entire microtask queue before it touches the next macrotask.
- Microtasks: promise callbacks (
.then,.catch,.finally, the continuation afterawait),queueMicrotask(),MutationObserver. - Macrotasks:
setTimeout,setInterval, I/O, rendering, user events.
js
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// 1, 4, 3, 2
3 beats 2 even though the timeout asked for 0 ms: the promise callback is a microtask and runs before the loop moves on to timers.
Drained completely, not one at a time
If a microtask queues another microtask, that one runs in the same pass too. An infinite chain will starve the page — timers never fire and nothing repaints:
js
function loop() {
Promise.resolve().then(loop);
}
loop(); // freezes the tab
A setTimeout recursion does not do this, because each iteration yields back to the event loop.
Why it matters in practice
- Anything after
awaitis a microtask, so it runs before the next timer or render — that is what makes awaited code feel immediate. - Rendering happens between macrotasks, never in the middle of the microtask queue. Long microtask chains delay paint and make the UI feel stuck.
- When you need to break up heavy work so the browser can draw, reach for
setTimeoutorscheduler.yield(), notqueueMicrotask().
