1

While reading a few articles about Event Loop and how it works I came across this quote:

Immediately after every macrotask, the engine executes all tasks from microtask queue, prior to running any other macrotasks or rendering or anything else.

And the quote kinda confused me, so I'd like to share my thoughts on that, and then hear whether I'm thinking in the right direction, or I'm dead wrong

At beginning, this quote sounded like macrotasks have priority over microtasks, and I ran following code:

const resolvedPromise = Promise.resolve('Microtask (Promise)');
    
setTimeout(() => {
  console.log('Macrotask (setTimeout)'); // (3)
}, 0);
    
resolvedPromise.then(data => console.log(data)); // (2)
    
console.log('Synchronous Code'); // (1)

As it turned out, the order was still synchronous code first, then microtask followed by macrotask, which got me confused. Then, I googled more and found that some say that the first macrotask is the script itself.

So, basically, whole script is being executed and at that moment other macrotasks & microtasks are being put into their respective queues. After reaching the last line of code, Microtasks are executed, then newly found macrotasks from macrotask queue (I believe I can say Callback Queue too, right?) are being executed, and if any macrotask introduces a new microtask, then when that macrotask stops executing, the new microtask is executed, and so on.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
RBRay3601
  • 45
  • 4
  • 2
    "*At beginning, this quote sounded like macrotasks have priority over microtasks,*" no, it doesn't? It just says that after a macrotask is finished, it will execute microtasks before doing another macrotask. This is the exact opposite - microtasks have priority. – VLAZ Aug 30 '22 at 09:29
  • "*(I believe I can say Callback Queue too, right?)*" you could but that's a useless term. All tasks are essentially "callbacks". Macro or micro. `setTimeout(fn)` and `Promise.resolve().then(fn)` will both enqueue the callback `fn` but to two different queues. You only designate one of the queues as "the callback queue" - why not the other? It's a rather arbitrary split. Moreover, callbacks don't have to be enqueued anywhere `arr.forEach(fn)` will execute the callback synchronously. Thus "the callback queue" becomes even muddier as a name - not all callbacks go there. – VLAZ Aug 30 '22 at 09:33
  • "*if any macrotask introduces a new microtask, then when that macrotask stops executing, the new microtask is executed*" this is exactly what the quote you have at the beginning of your question says. – VLAZ Aug 30 '22 at 09:34
  • 1
    There are [**dozens**](/search?q=%5Bjs%5D++microtask) of answered questions on this topic. Please search carefully before posting, all the basic stuff is already **well**-covered. – T.J. Crowder Aug 30 '22 at 09:37
  • The best is probably to forget about (macro)tasks here, that will just confuse things out. To put things blunt, every time the JS *[execution context stack](https://tc39.es/ecma262/#execution-context-stack)* is empty, there is a [microtask checkpoint](https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint). It doesn't matter if you were in a task, in a callback, or even for all that matters, in a microtask. – Kaiido Aug 30 '22 at 09:39

0 Answers0