The Node.js Event Loop
The event loop is what allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded.
Phases of the Event Loop
The event loop has several phases, each with a FIFO queue of callbacks to execute:
setTimeout() and setInterval()setImmediate() callbacks are invoked heresocket.on('close', ...)Understanding process.nextTick()
process.nextTick() is not technically part of the event loop. It's processed after the current operation completes, before the event loop continues.
console.log('Start');setTimeout(() => console.log('Timeout'), 0);
setImmediate(() => console.log('Immediate'));
process.nextTick(() => console.log('NextTick'));
Promise.resolve().then(() => console.log('Promise'));
console.log('End');
// Output:
// Start
// End
// NextTick
// Promise
// Timeout (or Immediate)
// Immediate (or Timeout)
Microtasks vs Macrotasks
process.nextTick, Promise.then, queueMicrotasksetTimeout, setInterval, setImmediate, I/OMicrotasks are processed between each phase of the event loop.
Avoiding Event Loop Blocking
// Bad - blocks the event loop
function processLargeArray(array) {
array.forEach(item => heavyComputation(item));
}// Good - yields to the event loop
async function processLargeArrayAsync(array) {
for (const item of array) {
await heavyComputation(item);
await new Promise(resolve => setImmediate(resolve));
}
}