New Changes to the Timers and Microtasks in Node v11.0.0 ( and above)

New Changes to the Timers and Microtasks in Node v11.0.0 ( and above)

gednanetwork April 26, 2014

This article is a short follow up to my original article series about Node.js Event Loop. In the original article series, I discussed in detail about Timers, setImmediateprocess.nextTick, Promises and many more.

However, since Node.js v11.0.0, there are some significant changes to the behavior of setTimeoutsetImmediateprocess.nextTick and Promises. In this article, I’m going to discuss these new changes along with some comparisons of the functionality between Node < v11.0.0 and Node ≥ v11.0.0. If you miss any of my previous articles about Node.js Event loop, I recommend you read them from the following links and return here to see the new changes introduced in Node v11.0.0.

  • Reactor Pattern and the Big Picture
  • Timers and Immediates
  • Promises, Next-Ticks and Immediates
  • Handling I/O
  • Event Loop Best Practices

Rationale

If you run the following piece of code in the browser and node separately, you’ll get contradicting results.

In the browser, you will get:

timeout1
timeout2
promise resolve
timeout3
timeout4

However, in Node versions below 11.0.0, you’ll get the following output:

timeout1
timeout2
timeout3
timeout4
promise resolve

In Node JS implementation, process.nextTick callbacks and microtasks (e.g, promise callbacks) were executed between each phase of the event loop when the C++/JavaScript boundary is crossed. Therefore, all timer callbacks are executed in the timers phase of the event loop before the Promise callback is executed which resulted in the above output.

However, this contradicting output between the browser and Node has been under discussion for a while and a feature (or a fix) has been landed in Node.js v11.0.0 to follow the browser behavior. With this feature, Node.js v11.0.0 or above will output the following which matches the browser’s output:

timeout1
timeout2
promise resolve
timeout3
timeout4

See the following comparison between Node v10.15.1 and Node v11.10.0:

This change not only affects setTimeout, but also affectssetImmediate. Let’s try to run the following code in Node v10 and Node v11 and see how the output is different.

Node v10 and Node v11 clearly give two different outputs as follows:

This behavior is quite the same if you replace Promise.resolve().then with process.nextTick, because microtasks are run after the process.nextTickcallbacks are run. Let’s try to run the following snippet:

The output of Node v10 and Node v11 for the above script is as follows:

What happens here?

With the new changes in Node v11, nextTick callbacks and microtasks will run between each individual setTimeout and setImmediate callbacks, even if the timers queue or the immediates queue is not empty. In terms of setTimeout and Promise callbacks, the new changes in Node v11 matches the browser behavior which improves the reusability of browser JavaScript in Node.js. However, this significant change could potentially break existing Node.js applications which explicitly rely on the old behavior. Therefore, if you are upgrading to Node v11 or above (preferably the next LTS v12), you might need to consider this as important.