Node.js › Event Loop & Non-blocking IO

What is the poll phase of the event loop, and under what specific conditions does it block waiting versus move on immediately?

Advanced

Answer

The poll phase retrieves new I/O events and executes their associated callbacks -- if the poll queue isn't empty, it processes callbacks until the queue is exhausted or a system-dependent hard limit is reached; if the poll queue IS empty, the loop checks whether any setImmediate() callbacks are scheduled (if so, it ends the poll phase immediately to proceed to the check phase) or whether any timers are due to fire soon (if so, it wraps back to the timers phase) -- otherwise, with genuinely nothing else pending, it will block here waiting for new I/O events to arrive, which is how Node.js avoids busy-waiting/spinning the CPU when idle.
// If there's truly nothing else for the event loop to do,
// it blocks efficiently in the poll phase rather than spinning the CPU
setTimeout(() => {
  console.log('This fires after the specified delay, not immediately,\n' +
  'because the loop was blocked efficiently in poll with nothing else to process');
}, 5000);
Real-world example A long-running Node.js CLI tool that's simply waiting for a scheduled task to fire in the future shows near-zero CPU usage in the interim, precisely because the event loop is efficiently blocked in the poll phase rather than continuously checking a condition in a busy loop.

Common follow-ups: How does this efficient blocking behavior in poll relate to why Node.js processes typically show very low idle CPU usage?;What happens to the poll phase's behavior specifically when there are active immediate callbacks waiting?