7

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 ?

13
  • "(the microtask queue has priority over the macrotask queue)" it doesn't. That's not a priority system here, (in an HTML event loop) it's just that there is a microtask checkpoint when the callstack is empty, and that this checkpoint will run every microtasks queued (even the ones queued from that checkpoint). A priority system would imply heuristics to determine what should be executed next, and for instance it would allow that after n times such task is executed, it executes one other task. Here there is no choice, no heuristic and no priority. Commented Jul 30, 2022 at 15:26
  • 1
    Also, setTimeout is very bad for testing anything since in node (and recently in Chrome, but I think they fixed it there now), there is a minimum 1ms timeout. Commented Jul 30, 2022 at 15:31
  • @Kaiido I've read the following three articles that suggest that the microtask queue has priority over the macrotask queue: blog.insiderattack.net/… serhiikoziy.medium.com/… javascript.info/event-loop. Please give me a detailled answer if you don't agree because it's hard for me (and other users as well) to understand this concepts from a small comment Commented Jul 30, 2022 at 15:40
  • 1
    I unfortunately lack the time to explain clearly how the event loop in browsers works, and I lack knowledge about how node's event loop works to post a valid answer to that question. But to make my first comment clearer, in a browser you can be sure that the microtask queue will be emptied after any task, actually it will be visited many times per event loop iteration. I'm saying this is not a priority system because there is actually one in browsers, which will make for instance UI tasks like dispatching click events have an higher priority than e.g network tasks caused by fetch. Commented Jul 30, 2022 at 15:54
  • @Kaiido That minimum timeout depends on the OS. On Windows it may be 1ms but on Linux it is typically 10ms. This is because it depends on the OS's tick/jiffy - the timer interrupt the OS uses to execute the OS instead of your programs. Linux has higher tick time because it is a server oriented OS that was designed to optimise throughput. Windows was designed to optimise GUI response (and gaming). The shorter the tick time the higher percentage of time the CPU is executing OS functions and that means the less CPU time your program gets. Commented Jul 30, 2022 at 18:08

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

" But in NodeJS versions before v11.0.0, the micro-task queue is drained only in between each two phases of the event loop." However, you've said that " The microtasks are executed after each of those macrotasks, just like in the browser.". So what is right ? Are microtasks dequeued after every single phase or after each 2 phases ?
The old (confusing, deprecated) behaviour was to run them after (all tasks in) every phase. The new (regular) behaviour is to run them after every task in every phase. "So what is right?" - it depends on your nodejs version! There is no "right" or "wrong".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.