Frontend · interactive
The browser event loop
Predict the output before you press play. One thread runs your script, then every queued microtask, then (maybe) a render, then the next task. A promise callback always beats a zero-millisecond timer.
console.log('A')
setTimeout(() => console.log('B'), 0)
Promise.resolve().then(() => console.log('C'))
queueMicrotask(() => console.log('D'))
console.log('E')Call stack
- script
Microtasks
- empty
Tasks
- empty
Render step
waiting for an empty stack and microtask queue
console: —
The script starts running on the call stack.
Run the script to the end
Synchronous code runs first, start to finish. Timers and promises only queue callbacks.
A, E
Drain every microtask
Promise callbacks and queueMicrotask run next, all of them, including any they add. Loop forever here and the page freezes.
C, D
Render if a frame is due
Style, layout and paint happen between tasks, about every 16 ms. Long tasks delay them: that's jank.
requestAnimationFrame callbacks run here.
Take one task from the queue
Timers, clicks and network callbacks are tasks. One runs, then microtasks again, then maybe a render.
Output: A E C D B
In production
Tools and technologies
Every browser follows the same HTML event loop spec.
Not tied to one language — use these names when you search docs or design a system.