setImmediate vs setTimeout in Node.js

In Node.js, setImmediate() and setTimeout() are both timer functions used to schedule asynchronous code execution, but they operate in different phases of the Node.js event loop. setTimeout() executes a callback after a specified threshold of time during the Timers phase, whereas setImmediate() is designed to execute a script in the Check phase immediately after the current I/O cycle completes. Understanding their behavior within the event loop allows developers to control task prioritization and write more predictable asynchronous code.

The Event Loop Lifecycle

To understand how both functions differ, it is essential to look at the phases of the libuv event loop in Node.js:

  1. Timers Phase: Executes callbacks scheduled by setTimeout() and setInterval().
  2. Pending Callbacks Phase: Executes I/O callbacks deferred to the next loop iteration.
  3. Idle, Prepare Phase: Used only internally by Node.js.
  4. Poll Phase: Retrieves new I/O events and executes I/O-related callbacks.
  5. Check Phase: Executes callbacks invoked by setImmediate().
  6. Close Callbacks Phase: Executes close callbacks, such as socket.on('close', ...).

Key Differences

1. Phase of Execution

2. Execution Order in the Main Context

When called from within the main module (outside of any I/O operation), the execution order of setTimeout() and setImmediate() is non-deterministic because it depends on the performance of the system and process startup time.

setTimeout(() => {
  console.log('setTimeout');
}, 0);

setImmediate(() => {
  console.log('setImmediate');
});

3. Execution Order Within an I/O Cycle

When both functions are called inside an I/O callback (like reading a file or network request), setImmediate() is always executed before setTimeout().

const fs = require('fs');

fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('setTimeout');
  }, 0);

  setImmediate(() => {
    console.log('setImmediate');
  });
});

Output:

setImmediate
setTimeout

Why this happens: The file read completes in the Poll phase. Once the callback executes, the event loop proceeds directly to the Check phase to run setImmediate(), rather than looping back to the Timers phase.

Summary Comparison

Feature setTimeout() setImmediate()
Event Loop Phase Timers phase Check phase
Delay Parameter Accepts a time delay (e.g., 1000ms) No delay parameter; runs immediately after I/O
Minimum Threshold 1ms (when set to 0) None
Inside I/O Cycle Runs after the Check phase (in the next loop) Always runs before setTimeout

When to Use Which