What are the main phases of the Node.js event loop?
Timers, pending callbacks, idle/prepare, poll, check, and close callbacks. Timers run setTimeout callbacks, poll collects I/O, check runs setImmediate, and microtasks are drained between steps.
Explain it simply
Think of a security guard doing rounds in a hostel, visiting the same checkpoints in the same order, again and again. Each checkpoint has its own to-do list. At each stop he finishes the tasks that are ready and moves on.
The loop, run by a C library called libuv, visits these in order:
- Timers: runs callbacks of
setTimeoutandsetIntervalwhose time has come. - Pending callbacks: some deferred system-level callbacks, such as certain network errors.
- Idle, prepare: internal use only.
- Poll: gets new I/O events (file reads finished, sockets with data) and runs their callbacks. If nothing is ready, it may wait here.
- Check: runs
setImmediatecallbacks. - Close callbacks: things like
socket.on("close").
Between each callback, Node empties the process.nextTick queue and then the promise microtask queue.
Example
const fs = require("fs");
fs.readFile(__filename, () => {
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
});
// prints inside an I/O callback, always: immediate, then timeoutInside an I/O callback the loop is in the poll phase, so the next stop is check, so setImmediate always wins.
What to say in the interview
"The loop cycles through timers, pending, poll, check and close phases. I/O callbacks run in poll, setImmediate in check, and microtasks run between callbacks. That ordering explains why immediate beats a zero-delay timer inside I/O."
Common mistakes
- Believing the event loop is multi-threaded; callbacks run on one thread.
- Memorising phases without knowing where setTimeout and setImmediate sit.