6 Phases in Node.js Event Loop: Are They Sequential?

6 phases of the Event Loop in Node.js execute in a specific sequential order, but their behavior is influenced by the tasks queued in each phase and the priority of microtasks (like process.nextTick and Promises).

Here’s the sequential order of the Event Loop phases and how they operate:

1. Timers Phase

  • What Happens: Executes callbacks scheduled by setTimeout and setInterval if their delay has expired.
  • Key Note: If there are no due timers, the Event Loop immediately moves to the next phase.

2. Pending Callbacks Phase

  • What Happens: Processes I/O-related callbacks deferred from the previous cycle (e.g., TCP errors or operations like socket.on('error')).
  • Key Note: This phase is mostly used internally by Node.js and is less visible in application-level code.

3. Idle, Prepare Phase

  • What Happens: Used internally by Node.js for preparing the next iteration of the Event Loop.
  • Key Note: Not directly accessible to developers, so you usually don’t interact with this phase.

4. Poll Phase

  • What Happens:
    • Retrieves new I/O events (e.g., reading files, network responses).
    • Executes I/O callbacks if there are pending ones in the queue.
    • If no I/O callbacks are pending:
      • The Event Loop will either block and wait for new events or move to the Check Phase if setImmediate callbacks are pending.
  • Key Note: This is one of the most important phases for handling I/O.

5. Check Phase

  • What Happens: Executes callbacks registered by setImmediate.
  • Key Note: setImmediate is processed here, ensuring it runs after the Poll Phase.

6. Close Callbacks Phase

  • What Happens: Executes callbacks for resources that are closed (e.g., socket.on('close')).
  • Key Note: Typically used for cleanup operations.

Microtasks Queue

While the 6 phases are processed sequentially, microtasks have higher priority and can interrupt the Event Loop after any phase.

Microtasks include:

  • process.nextTick
  • Promise resolution handlers

At the end of each phase:

  1. Node.js processes all microtasks in the microtask queue.
  2. Once the microtask queue is cleared, the Event Loop proceeds to the next phase.

Does the Sequence Always Apply?

Yes, the phases are always processed in this sequential order, but:

  1. Phases may be skipped:
    • If a phase has no queued callbacks or tasks (e.g., no timers in the Timers Phase), the Event Loop immediately moves to the next phase.
  2. Microtasks interrupt the sequence:
    • Before transitioning to the next phase, Node.js will process all pending microtasks.

Key Observations

  1. setTimeout vs setImmediate:
    • setTimeout is executed in the Timers Phase.
    • setImmediate is executed in the Check Phase.
    • If both are queued without delays, setImmediate will usually execute first because the Poll Phase processes I/O and moves to the Check Phase before timers.
  2. process.nextTick vs Promises:
    • Both are microtasks, but process.nextTick has higher priority than Promises and executes before them.

Conclusion

The 6 phases of the Event Loop are processed sequentially, but the microtask queue introduces interruptions between phases, ensuring high-priority tasks like process.nextTick and Promises are handled promptly. This strict order with interleaved microtasks is what enables Node.js to efficiently handle asynchronous tasks on a single thread.

Leave a comment

I’m Tran Minh

Hi, I’m Trần Minh, a Solution Architect passionate about crafting innovative and efficient solutions that make technology work seamlessly for you. Whether you’re here to explore the latest in tech or just to get inspired, I hope you find something that sparks joy and curiosity. Let’s embark on this exciting journey together!

Let’s connect