awesome-everything RU
↑ Back to the climb

Browser & Frontend Runtime

Event loop: predict the output

Crux Read real JS snippets and predict the exact execution order — sync code, microtasks, tasks, rAF, and the Node phase ordering.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min

Predicting the exact log order is the cleanest test of whether you truly hold the loop’s model. Read each snippet, trace which queue every callback lands in, and pick the output a careful engineer would predict.

Goal

Practise the trace you run mentally in every async bug: classify each callback as sync, microtask, task, or frame work, and order them by the loop’s fixed rules — including the Node-specific reordering.

Snippet 1 — sync, microtask, and task in one turn

console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');
Quiz

What does this log, in order?

Snippet 2 — async/await desugared

async function run() {
  console.log('1');
  await null;            // suspends; resume is queued as a microtask
  console.log('2');
}
console.log('3');
run();
console.log('4');
Promise.resolve().then(() => console.log('5'));
Quiz

What is the output order?

Snippet 3 — rAF versus microtask versus task

console.log('start');
requestAnimationFrame(() => console.log('raf'));
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');
Quiz

Assuming the browser renders a frame on this turn, what is the most reliable ordering?

Snippet 4 — Node phase ordering

// Run with: node script.js
const fs = require('fs');
fs.readFile(__filename, () => {
  setTimeout(() => console.log('timeout'), 0);
  setImmediate(() => console.log('immediate'));
  process.nextTick(() => console.log('nextTick'));
  Promise.resolve().then(() => console.log('promise'));
});
Quiz

Inside this I/O callback, what is the deterministic output order in Node?

Recap

Every async ordering puzzle resolves with the same trace: all synchronous code first, then the microtask checkpoint drains to empty (await resumes and .then callbacks in FIFO order), then the render step runs rAF on a frame boundary, then the loop pulls the next task (setTimeout, MessageChannel). Node layers a phase machine on top: process.nextTick drains before microtasks between every phase, and inside an I/O callback setImmediate (check phase, this iteration) beats setTimeout(0) (timers phase, next iteration). Classify each callback by queue, then order by these fixed rules — never by source position.

Continue the climb ↑Event loop: rescue an interaction from INP hell
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.