Each loop iteration goes through six phases in order. Each phase has its own queue of callbacks:
- timers runs
setTimeoutandsetIntervalcallbacks whose time has passed. - pending callbacks runs some system-level callbacks delayed from the previous iteration, such as certain TCP errors.
- idle, prepare is for Node's internal use.
- poll gets new I/O events and runs their callbacks. If nothing else is scheduled, the loop waits here for I/O, but only until the next timer is due.
- check runs
setImmediatecallbacks. - close callbacks runs handlers like a socket's
closeevent.
Two queues sit outside the phases. After every single callback, Node empties the process.nextTick queue first. Then it empties the promise microtask queue. So these callbacks always run before the loop moves on.
The process exits when nothing keeps the loop alive. That means no timers, no open handles (like sockets or servers) and no pending requests.
- The order is: timers, pending callbacks, idle/prepare, poll, check, close callbacks.
- The poll phase runs I/O callbacks and waits for I/O when the loop is idle.
setImmediatecallbacks run in the check phase.- After each callback, Node empties the nextTick queue, then the promise microtask queue.
- The loop exits when nothing keeps it alive.