This is the Node event loop.
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘ ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ ┌─────────────┴─────────────┐ └───────────────┘
│ │ check │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘
I know that Node uses the V8 JS engine and I've learned that V8 has its own event loop that embedders are free to replace or extend. In Chrome for example, there is a macrotask and a microtask queue (the microtask queue has priority over the macrotask queue) and the event loop pushes callbacks from those queues once the call stack of the main thread is empty.
You can queue microtasks on the microtask queue manually using the queueMicrotask
function.
I've tried using this function in Node as well and it works. My question is, where are microtasks queued on the event loop ? In what phase are they queued in ? Do they have a phase that is specific for them or are they mixed up with other kinds of callbacks ?
I've tried this code to get an idea of what has priority in the Node event loop :
const hello_world =() => {
console.log("Hello World 2");
};
queueMicrotask(hello_world);
setTimeout(
() => {
console.log("Hello World 3");
},
0
);
console.log("Hello World 1");
/*
OUTPUT:
Hello World 1
Hello World 2
Hello World 3
*/
So, I can see that microtasks have priority over timers (which are considered macrotasks in the chrome event loop) but where are the microtasks enqueue in the event loop in Node ?
And furthermore, what has priority over what in the Node event loop ? I know that in Chrome for example, the microtask queue has priority over the macrotask queue, but what phase has priority over what phase in the Node event loop ?
CodePudding user response:
Where are the microtasks enqueue in the event loop in Node?
They can be enqueued anywhere - you probably meant to ask where they are dequeued :-)
The article you've read answers this:
The event loop should process the micro-task queue entirely, after processing one macro-task from the macro-task queue. […] But in NodeJS versions before v11.0.0, the micro-task queue is drained only in between each two phases of the event loop.
All those "phases" in your diagram are for processing macro tasks: timers, pending tasks, polled events, immediates, close events. The microtasks are executed after each of those macrotasks, just like in the browser.
The only exception weirdness is the special case of process.nextTick
, which does not enqueue a macrotask either. This article distinguishes between a "promises microtask queue" and a "nextTick
microtask queue" - the overarching term "microtask" being used for everything that comes before the next macrotask.
What phase has priority over what phase in the Node event loop?
There is no "priority". As the diagram shows nicely, they are executed one after the other, repeatedly, always in the same order, ad nauseam. Some phases have limits on the number of tasks to execute at once, to prevent starving the other phases, then the remaining tasks are run simply at the next time when it's the phase's turn again.