All three run a function later, but at different moments:
process.nextTick(fn)runsfnas soon as the current operation finishes. It runs before promise microtasks and before the event loop moves on.setImmediate(fn)runs in the check phase. This phase comes right after the poll phase (where Node waits for and handles I/O) in the current loop iteration.setTimeout(fn, 0)runs in the timers phase, once at least 1 ms has passed. Node treats 0 as 1.
The names are confusing: nextTick is the more immediate one.
When to use each:
- Use
nextTickrarely. One good case: emit an event or call a callback asynchronously, so the caller first has time to attach listeners. Node empties the wholenextTickqueue before it continues. So if anextTickcallback keeps scheduling morenextTickcalls, I/O never gets a turn. This is called starving I/O. - Use
setImmediateto let I/O run first, for example when you break a long job into chunks. - Use
setTimeoutwhen you really need a delay.
nextTickruns before promises and before the event loop continues.setImmediateruns in the check phase, after the poll phase.setTimeout(0)runs in the timers phase, after at least 1 ms.- Recursive
nextTickcalls starve I/O. RecursivesetImmediatecalls do not. - Prefer
setImmediatewhen you want to give I/O a turn.