I've seen this question recently since I'm trying to clarify my concept about Javascript event loop and microtasks. Although the top answer in that thread got more than 100 upvotes, I still have some doubts with some of the descriptions in that.
Here's the code from that thread:
1 Promise.resolve('A').then(function (a) {
2 console.log(2, a);
3 return 'B';
4 }).then(function (a) {
5 Promise.resolve('C').then(function (a) {
6 console.log(7, a);
7 }).then(function (a) {
8 console.log(8, a);
9 });
10 console.log(3, a);
11 return a;
12 }).then(function (a) {
13 Promise.resolve('D').then(function (a) {
14 console.log(9, a);
15 }).then(function (a) {
16 console.log(10, a);
17 });
18 console.log(4, a);
19 }).then(function (a) {
20 console.log(5, a);
21 });
22
23 console.log(1);
24
25 setTimeout(function () {
26 console.log(6)
27 }, 0);
The author said the following comment.
Anyway, in your case, it's a scheduling race and the engine you are running decides to run the inner .then() handler that's defined on line 5 next and thus you see the 7 "C" specified on line 6. It then returns nothing so the resolved value of this promise becomes undefined.
In my understanding of the microtask queue, it's the implementation of the job queue of ECMAScript in the browser environments. From the HTML standard, each event loop has only one microtask queue. As a result, if this code runs in a browser environment, while it goes to line 5, the .then() on line 5 is pushed to the microtask queue since the Promise fulfilled immediately, and on line 12, because the previous Promise is also fulfilled and returned, the .then() on line 12 is pushed to the microtask queue. Therefore, I don't see any scheduling race here since all the promises are fulfilled immediately and we only have one microtask queue.
Moreover, even we run this code outside any environment, such as browsers or Node.js, from the ECMAScript, we should at least have two kinds of job queues that are PromiseJobs queue and ScriptJobs queue. Anyway, it sounds like the implementation of JavaScript engine also groups the Job Queues by types. Hence, I think we will also have only one PromiseJob queue (or I'm wrong?), and still have no scheduling race here.
The same question also came up when I saw the description about line 13 and line 19.
Again, all synchronous code is done so it goes back to the scheduler again and it decides to run the .then() handler defined on line 13. That runs and you get the output 9 "D" and then it goes back to the scheduler again.
Could someone tell me are there really scheduling races here or not?