There's an important semantic with microtasks and nextTicks which depends on the Node version.
Before Node v11, nextTick queue was executed between each phase of the event loop (timers, I/O, immediates, close handlers are the four phases). Therefore, before Node v11, promise callbacks were also executed between each phase in the event loop. (I've written about this in detail here: https://blog.insiderattack.net/promises-next-ticks-and-immediates-nodejs-event-loop-part-3-9226cbe7a6aa)
However, starting from Node v11, event loop jumps to microtask
queue whenever a microtask
is added to the microtask queue as part of the execution of the program. You can experiment this with the following snippet. The same applies to nextTick queue too. You can read more here: https://blog.insiderattack.net/new-changes-to-timers-and-microtasks-from-node-v11-0-0-and-above-68d112743eb3
setImmediate(() => console.log('timeout1'));
setImmediate(() => {
console.log('timeout2')
Promise.resolve().then(() => console.log('promise'))
});
setImmediate(() => console.log('timeout3'));
setImmediate(() => console.log('timeout4'));
The output of the above code changes depending on the Node.js version as follows:
$ node -v
v10.19.0
$ node test.js
timeout1
timeout2
timeout3
timeout4
promise
$ nvm use 11
Now using node v11.15.0 (npm v6.7.0)
$ node test.js
timeout1
timeout2
promise
timeout3
timeout4
Therefore it's important to know that: nextTicks
and microtasks
have an even higher priority in Node versions >=11, because they get the chance to be processed within the current phase of the event loop. But in earlier Node versions, nextTicks
and microtasks
are executed at the end of each phase of the loop.
On a side note, it's important to know that microtasks
queue is a part of v8
engine and not maintained in Node.js runtime. However, Node.js event loop instructs v8
to run all microtasks
, once Node.js finishes with the nextTick
queue. Therefore, promise callbacks are executed after nextTick
queue.