The cheatsheet
Everything the interactive cases teach, on one page. Every rule links to the case where you can watch it happen.
Browser and Node are different loops — they get separate sections below. Last reviewed 29 July 2026.
Browser
One iteration of the event loop:
sync code, a timer callback, an event handler
including ones queued during the drain
rAF → style → layout → paint — not every iteration
from one of several task queues
| API | Where the callback goes | When it runs | Most common misconception | Watch it |
|---|---|---|---|---|
| setTimeout / setInterval | Task queue (timer task source) | After the current task and every queued microtask; delay is a minimum | “The delay is an exact schedule” | How Timers Really Run → |
| Promise.then / .catch / .finally | Microtask queue | At the microtask checkpoint after the current task; queue drains completely | “Registered earlier = runs earlier, even across queues” | How Promises Run → |
| A chained .then() | Microtask queue — but only when the previous link settles | One extra trip through the queue per link | “A chain runs to completion as one unit” | How Promise Chains Run → |
| Code after await | Microtask queue, as a continuation, when the awaited promise settles | FIFO with all other microtasks — no special priority | “await blocks the thread / defers the whole function” | How await Runs → |
| queueMicrotask | Microtask queue | Same lane as promise callbacks, FIFO between them | “It is somehow different from a resolved .then” | How Promises Run → |
| fetch | Browser network layer; resolves its promise on response HEADERS | Continuation queues as a microtask when headers arrive; body is a second async stage | “await fetch() waits for the whole body · a 404 rejects” | How fetch Runs → |
| requestAnimationFrame | Registered for the next rendering opportunity | During the rendering step, after all microtasks, just before paint | “It fires every 16ms like a timer” | How Rendering Fits In → |
Goes to · Task queue (timer task source)
Runs · After the current task and every queued microtask; delay is a minimum
“The delay is an exact schedule”
Goes to · Microtask queue
Runs · At the microtask checkpoint after the current task; queue drains completely
“Registered earlier = runs earlier, even across queues”
Goes to · Microtask queue — but only when the previous link settles
Runs · One extra trip through the queue per link
“A chain runs to completion as one unit”
Goes to · Microtask queue, as a continuation, when the awaited promise settles
Runs · FIFO with all other microtasks — no special priority
“await blocks the thread / defers the whole function”
Goes to · Microtask queue
Runs · Same lane as promise callbacks, FIFO between them
“It is somehow different from a resolved .then”
Goes to · Browser network layer; resolves its promise on response HEADERS
Runs · Continuation queues as a microtask when headers arrive; body is a second async stage
“await fetch() waits for the whole body · a 404 rejects”
Goes to · Registered for the next rendering opportunity
Runs · During the rendering step, after all microtasks, just before paint
“It fires every 16ms like a timer”
Node.js
Phases (timers → pending → poll → check → close), with two queues drained between every phase transition:
e.g. expired timer callbacks
completely — Node-only, highest priority
promise callbacks, queueMicrotask
poll for I/O, run setImmediate, …
| API | Where the callback goes | When it runs | Most common misconception | Watch it |
|---|---|---|---|---|
| process.nextTick | nextTick queue (Node-only, above microtasks) | Drained completely between phases, BEFORE promise microtasks — in CommonJS | “It is just another microtask” | How Node Runs It → |
| Promise.then (Node) | Microtask queue | After the nextTick queue, before the loop advances a phase | “Node ordering matches the browser exactly” | How Node Runs It → |
| Top-level ESM code | Evaluated as a module job — inside a microtask | Already inside a checkpoint, so pending promises finish before nextTick is revisited | “.cjs and .mjs print the same order” | How Node Runs It → |
Goes to · nextTick queue (Node-only, above microtasks)
Runs · Drained completely between phases, BEFORE promise microtasks — in CommonJS
“It is just another microtask”
Goes to · Microtask queue
Runs · After the nextTick queue, before the loop advances a phase
“Node ordering matches the browser exactly”
Goes to · Evaluated as a module job — inside a microtask
Runs · Already inside a checkpoint, so pending promises finish before nextTick is revisited
“.cjs and .mjs print the same order”
The nextTick-before-promises ordering holds for CommonJS. Top-level ESM code already runs inside a microtask, which flips it — same file, different order.
Seven rules that settle most questions
- Synchronous code runs to completion. Nothing queued can interrupt it — not an expired timer, not a settled promise.
- A timer delay is a floor, never a schedule. "0ms" means "eligible as soon as the stack is empty", and a busy thread stretches every delay.
- After the stack empties, the entire microtask queue drains before the next task — including microtasks queued during the drain. This is also how microtask chains starve rendering.
- Registration order only decides ties WITHIN one queue. Across queues, queue type wins.
- Each link of a promise chain costs one trip through the queue. Independent chains interleave one link at a time.
- await suspends the function, never the thread. The rest of the function becomes an ordinary microtask when the awaited promise settles — no special priority.
- await fetch() unblocks on response headers; reading the body is a second async stage. HTTP error statuses resolve — only network failures reject.
Terminology: the HTML spec defines tasks and microtasks; "macrotask" is community shorthand for an ordinary task. Browsers keep several task queues, not one.
Sources: HTML Standard — Event loop processing model · Node.js — The event loop, timers, and process.nextTick() · MDN — The event loop
Every ordering on this sheet is enforced by the same validation that runs the interactive cases — see methodology. Found an error? The site is wrong before you are; check the case page and its sources first, then tell us.