Asynchronous code and events

Understanding setImmediate()

Understand how Node.js setImmediate() runs a callback in the next event loop iteration, and how it differs from setTimeout(0) and process.nextTick().

8 minute lesson

~~~

setImmediate() schedules a callback for the check phase of a future event-loop iteration:

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

It means “run after the current work yields and the loop reaches the check phase,” not “run immediately” and not “run after exactly zero milliseconds.”

Compare the three queues:

  • process.nextTick() runs after the current JavaScript operation, before the event loop continues to another phase.
  • setTimeout(callback, 0) schedules a timer after a minimum delay threshold. The operating system and other work can delay it.
  • setImmediate() runs in the check phase, after the poll phase used for I/O callbacks.

From the top level of a script, the relative order of a zero-delay timeout and an immediate should not be treated as a contract:

setTimeout(() => console.log('timeout'), 0)
setImmediate(() => console.log('immediate'))

Inside an I/O callback, the immediate is scheduled for the check phase following that poll work and normally runs before a newly scheduled zero-delay timer:

import { readFile } from 'node:fs'

readFile(import.meta.filename, () => {
  setTimeout(() => console.log('timeout'), 0)
  setImmediate(() => console.log('immediate'))
})

process.nextTick() is not an ordinary event-loop phase. Recursively scheduling next-tick callbacks can starve timers and I/O because Node drains that queue before continuing. Use it for narrow API-ordering needs, not for breaking up large computations.

An Immediate normally keeps the process alive. Calling .unref() allows the process to exit if that callback is the only remaining work:

setImmediate(() => console.log('may run')).unref()

Ordering details can evolve with Node and its event-loop implementation. Write code around documented phase relationships, never a race observed once on your machine.

Your action is to run the top-level and I/O examples ten times on your Node version. Record the output, then add five recursive process.nextTick() calls and explain why an unbounded version would delay other work.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →