All 13

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:

1 Run one task

sync code, a timer callback, an event handler

2 Drain ALL microtasks

including ones queued during the drain

3 Possibly render

rAF → style → layout → paint — not every iteration

4 Select the next task

from one of several task queues

setTimeout / setInterval Watch →

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”

Promise.then / .catch / .finally Watch →

Goes to · Microtask queue

Runs · At the microtask checkpoint after the current task; queue drains completely

“Registered earlier = runs earlier, even across queues”

A chained .then() Watch →

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”

Code after await Watch →

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”

queueMicrotask Watch →

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”

requestAnimationFrame Watch →

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:

1 Run the current phase

e.g. expired timer callbacks

2 Drain the nextTick queue

completely — Node-only, highest priority

3 Drain microtasks

promise callbacks, queueMicrotask

4 Advance to the next phase

poll for I/O, run setImmediate, …

process.nextTick Watch →

Goes to · nextTick queue (Node-only, above microtasks)

Runs · Drained completely between phases, BEFORE promise microtasks — in CommonJS

“It is just another microtask”

Promise.then (Node) Watch →

Goes to · Microtask queue

Runs · After the nextTick queue, before the loop advances a phase

“Node ordering matches the browser exactly”

Top-level ESM code Watch →

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

  1. Synchronous code runs to completion. Nothing queued can interrupt it — not an expired timer, not a settled promise.
  2. 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.
  3. 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.
  4. Registration order only decides ties WITHIN one queue. Across queues, queue type wins.
  5. Each link of a promise chain costs one trip through the queue. Independent chains interleave one link at a time.
  6. await suspends the function, never the thread. The rest of the function becomes an ordinary microtask when the awaited promise settles — no special priority.
  7. 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.