setTimeout vs setImmediate vs process.nextTick

logicmason

Mark

Posted on April 22, 2019

setTimeout vs setImmediate vs process.nextTick

What's the difference between setTimeout(callback, 0) and process.nextTick(callback)? How about Node's setImmediate(callback)?

On the surface it appears that all three functions do the same thing—they execute the callback after the current event loop, but before anything else. The natural question to ask is, why are there three different functions? Let's run an experiment:

let racer = function() {
  setTimeout(() => console.log("timeout"), 0);
  setImmediate(() => console.log("immediate"));
  process.nextTick(() => console.log("nextTick"));
  console.log("current event loop");
}

racer()

We can see from the output that these callbacks aren't executed in the same order they were written in the source code.

[Running] node "/Users/logicmason/timeouts.js"
current event loop
nextTick
timeout
immediate

[Done] exited with code=0 in 0.203 seconds

Explanation

The first one executed was process.nextTick, which puts its callback at the front of the event queue. It will execute after the code currently being executed but before any I/O events or timers.

Next is "timeout". Since we passed setTimeout a timeout of 0, there's no additional enforced delay before its execution, and it is placed on into the timer queue during the next loop.

Finally, we have setImmediate, which is clearly not as immediate as its name suggests! Its callback is placed in the check queue of the next cycle of the event loop. Since the check queue occurs later than the timer queue, setImmediate will be slower than setTimeout 0.

All in all, the event loop looks like this:

timers -> IO -> poll -> check ->close -> timers -> ...

Timers: callbacks from setInterval or setTimeout
IO callbacks: callbacks from I/O events
Idle: used internally by Node between IO and Poll phases
Poll: retrieve new I/O events
Check: callbacks from setImmediate execute here
Close: handle closed connections like sockets

Challenge time!

What do you expect the output of the following code in Node to be?

let racer1 = function() {
  setTimeout(() => console.log("timeout"), 0);
  setImmediate(() => console.log("immediate"));
  process.nextTick(() => console.log("nextTick"));
}

let racer2 = function() {
  process.nextTick(() => console.log("nextTick"));
  setTimeout(() => console.log("timeout"), 0);
  setImmediate(() => console.log("immediate"));
}

let racer3 = function() {
  setImmediate(() => console.log("immediate"));
  process.nextTick(() => console.log("nextTick"));
  setTimeout(() => console.log("timeout"), 0);
}

racer1()
racer2()
racer3()

Was it what you expected?

Subscribe to more content from logicmason.com

💖 💪 🙅 🚩
logicmason
Mark

Posted on April 22, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Event loop in Node.js
eventloop Event loop in Node.js

June 25, 2024