Difference Between Microtask and MACrotask Within an Event Loop Context

Difference between microtask and macrotask within an event loop context

One go-around of the event loop will have exactly one task being processed from the macrotask queue (this queue is simply called the task queue in the WHATWG specification).
After this macrotask has finished, all available microtasks will be processed, namely within the same go-around cycle. While these microtasks are processed, they can queue even more microtasks, which will all be run one by one, until the microtask queue is exhausted.

What are the practical consequences of this?

If a microtask recursively queues other microtasks, it might take a long time until the next macrotask is processed. This means, you could end up with a blocked UI, or some finished I/O idling in your application.

However, at least concerning Node.js's process.nextTick function (which queues microtasks), there is an inbuilt protection against such blocking by means of process.maxTickDepth. This value is set to a default of 1000, cutting down further processing of microtasks after this limit is reached which allows the next macrotask to be processed)

So when to use what?

Basically, use microtasks when you need to do stuff asynchronously in a synchronous way (i.e. when you would say perform this (micro-)task in the most immediate future).
Otherwise, stick to macrotasks.

Examples

macrotasks: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering

microtasks: process.nextTick, Promises, queueMicrotask, MutationObserver

Where are microtasks executed in the node js event loop and how are its phases prioritised?

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.

Why is this microtask executed before macrotask in event loop?

My understanding is that the full microtask task queue is processed after each macrotask.

Yes. And the code that you ran, from console.log('start') to console.log('end'), is such a macrotask. After it ran to completion, the microtask queue with the promise callbacks is processed, and only after that the next macrotask (the timeout) gets to run.

Confusion in MicroTask Queue and MacroTask Queue

The wait function's promise resolves only after the setTimeout finishes - after a macrotask (a few milliseconds) In contrast, the Promise.resolve gets put onto the microtask queue, which will run first (often a millisecond or less). After the console.log(1) line runs, you'll have the following:

Microtask queue: .then(() => console.log(2)).then(() => console.log(3));

Macrotask queue: resolve (due to the setTimeout)

Microtask queue runs first, so 2 gets logged, then the next .then gets put onto the microtask queue, and 3 gets logged. Finally, the setTimeout macrotask runs, resolving the wait Promise, putting another .then onto the microtask queue, and shortly causing 4 to be logged.

Micro and macro tasks in JavaScript runtime

Three years later, of course, but we do have an answer for this now: the window.queueMicrotask() method has been added to allow adding a callback to the JavaScript runtime's microtask queue. I'm currently working on fleshing out a microtask guide on MDN Web Docs.



Related Topics



Leave a reply



Submit