The event loop is the heart of Node.js’s non-blocking I/O model. It enables JavaScript to perform asynchronous operations despite being single-threaded by offloading operations to the system kernel or thread pool whenever possible.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nodejs/node/llms.txt
Use this file to discover all available pages before exploring further.
Event Loop Overview
The event loop continuously processes callbacks and executes JavaScript code. It follows a specific set of phases, each with its own queue of callbacks to execute.Event Loop Phases
Each phase has a FIFO queue of callbacks to execute. The event loop will process all callbacks in a phase’s queue before moving to the next phase.Timers Phase
Executes callbacks scheduled by
setTimeout() and setInterval(). Timers are checked to see if their threshold has elapsed.Pending Callbacks Phase
Executes I/O callbacks deferred to the next loop iteration. These are callbacks for some system operations like TCP errors.
Poll Phase
Retrieves new I/O events and executes I/O-related callbacks. This is where most application code executes.
Timers Phase
Timers schedule callbacks to be executed after a minimum threshold in milliseconds.Timer Implementation
Node.js uses a priority queue to manage timers efficiently:Timers with the same timeout duration are grouped into a linked list and stored in a priority queue. This optimization reduces the overhead of managing thousands of timers.
Timer Precision
Example: Timer Execution
Poll Phase
The poll phase has two main functions:- Calculate how long it should block and poll for I/O
- Process events in the poll queue
Poll Phase Behavior
When the poll queue is not empty
When the poll queue is not empty
The event loop will iterate through its queue of callbacks, executing them synchronously until either:
- The queue has been exhausted
- The system-dependent hard limit is reached
When the poll queue is empty
When the poll queue is empty
One of two things will happen:
- If scripts have been scheduled by
setImmediate(), the event loop will end the poll phase and continue to the check phase - If no
setImmediate()is scheduled, the event loop will wait for callbacks to be added to the queue, then execute them immediately
Poll Phase Timeout
The poll phase calculates how long it should wait:- Timers scheduled to execute soon
- Pending
setImmediate()callbacks - Other phase requirements
setImmediate() vs setTimeout()
These two functions are similar but behave differently depending on the context.Check Phase vs Timers Phase
Execution Order Example
The order of execution depends on the performance of the process. If the event loop enters the timer phase before 1ms has elapsed,
setImmediate() executes first.Within an I/O Cycle
process.nextTick()
process.nextTick() is not technically part of the event loop. It has its own queue that is processed after the current operation completes, regardless of the current phase.
nextTick Queue
The nextTick queue is processed:- After each phase of the event loop
- After each operation in the current phase
Execution Order
Why nextTick Exists
Microtasks vs Macrotasks
Node.js distinguishes between two types of asynchronous tasks:Microtasks
Executed immediately after the currently executing script and before returning to the event loop:process.nextTick()callbacks (highest priority)- Promise callbacks (
.then(),.catch(),.finally()) queueMicrotask()callbacks
Macrotasks
Scheduled in event loop phases:setTimeout()/setInterval()(timers phase)setImmediate()(check phase)- I/O operations (poll phase)
- UI rendering (in browsers, not Node.js)
Processing Order
All microtasks are processed before moving to the next phase of the event loop. Within microtasks,
process.nextTick() has priority over Promises.Close Callbacks Phase
Handles cleanup when resources are closed:Internal Implementation
Event Loop in Practice
Blocking the Event Loop
Monitoring Event Loop
Related Topics
- Architecture - Overall Node.js architecture
- Async Programming - Working with asynchronous code
- Modules - Module loading and the event loop