Predict the output: setTimeout, a promise, process.nextTick and plain logs together
Synchronous code runs first, then process.nextTick callbacks, then promise callbacks (microtasks), then timers. So the order is sync, nextTick, promise, setTimeout.
Explain it simply
Picture a railway counter. The person at the window finishes the current customer completely (synchronous code). Before calling the next customer from the queue, they clear two small priority slips: first the nextTick slip, then the promise slip. Only then do they call the next ordinary customer, which is a timer or I/O callback.
Example
console.log("A");
setTimeout(() => console.log("B: timeout"), 0);
Promise.resolve().then(() => console.log("C: promise"));
process.nextTick(() => console.log("D: nextTick"));
console.log("E");
// prints:
// A
// E
// D: nextTick
// C: promise
// B: timeoutStep by step:
AandEare synchronous, so they print first.- When the main script ends, Node drains the nextTick queue, so
Dprints. - Then the promise microtask queue drains, so
Cprints. - The event loop then reaches the timers phase and
Bprints.
In an ES module file the order of D and C can differ, because the module itself runs inside a promise job. That is why most examples use CommonJS.
What to say in the interview
"Sync code first, then the nextTick queue, then promise microtasks, then the event loop phases where timers run. nextTick has higher priority than promises in CommonJS."
Common mistakes
- Thinking
setTimeout(fn, 0)runs immediately. - Starving the loop with recursive nextTick calls, which blocks I/O.