The title

If you’re not familiar with EventLoop, check out my other article event loops

  let a;
  const b = new Promise((resolve, reject) = > {
      console.log('promise1');
      resolve();
  }).then(function b1() {
      console.log('promise2');
  }).then(function b2() {
      console.log('promise3');
  }).then(function b3() {
      console.log('promise4');
  });

  a = new Promise(async (resolve, reject) => {
      console.log(a);
      await b;
      console.log(a);
      console.log('after1');
      await a
      resolve(true);
      console.log('after2');
  });

  console.log('end');
Copy the code

Promise1, undefined, end, promise2, promise3, promise4, Promise {pending}, after1

Analysis step by step

1. This code into script, the overall is a macro task, the first to execute the macro task, code from top to bottom

2. The first new Promise() calls the Promise constructor, which immediately executes the callback you passed (resolve, reject) =>{… }, needless to say, print ‘promise1’ and then execute resolve(). (The code in this callback can be viewed as synchronous code)

This is a big Promise, which will be fulfilled someday. This is a big Promise, which will be fulfilled someday. The first THEN will be called, which will be fulfilled soon

Microtask queue: [B1]Copy the code

This is a big pity. The following two THEN will not be executed, because b1 callback will be completed, and the new Promise will be returned.

5. Enter the second new Promise() and call the Promise constructor, executing the callback async (resolve, reject) =>{… }, this piece is also considered synchronous. The result of printing console.log(a) is’ undefined ‘. I think we called the Promise constructor and immediately printed the a variable. The Promise object hasn’t been created yet, so it hasn’t been assigned to the A variable

. a =new Promise(async (resolve, reject) => {
    console.log(a);
    await b;
    console.log(a);
    console.log('after1');
    await a
    resolve(true);
    console.log('after2');
});

console.log(a); // Promise {
      
       } if the a assignment is printed here, it is successful
      

console.log('end');
Copy the code

This is a big pity. 6. Await b will not be executed immediately, it will wait for the b3 callback to execute and return the new Promise {depressing}, await B can be seen as the following code:

// await B is waiting for the b3 callback to complete and return a new Promise object with success. Omitted code. Then (function b3() {
    console.log('promise4');
}).then(function b4() {
    console.log(a); 
    console.log('after1');
})

await b // promise.then(function b4() {console.log(a); console.log('after1'); })

Copy the code

7. Await a will never execute, it is waiting for itself

Console. log(‘end’), print ‘end’

9. The microtask queue is emptied immediately after the entire script execution (macro task)

  // The b1 callback is added to the microtask queue at step 3Microtask queue: [B1]// The task queue is a first-in, first-out policyMicrotask queue: []/ / to emptyThe B1 callback function puts the execution stack to execute/ / print promise2
    
Copy the code
  1. A new Promise {depressing} will be returned after the b1 callback is successfully executed, and the following THEN method will be called, and the B2 callback will be added to the microtask queue
Microtask queue: [b2]Copy the code

11. Clear the microtask queue again

Microtask queue: []/ / to emptyB2 callback function puts stack execution/ / print promise3

Copy the code

12. The b2 callback will return a new Promise {fulfilled}, invoke the following THEN method, and the B3 callback will be added to the microtask queue

Microtask queue: [B3]Copy the code

13. Clear the microtask queue again

Microtask queue: []/ / to emptyThe B3 callback puts the stack execution/ / print promise4

Copy the code

This is a big pity. 14. The b3 callback will return a new Promise {depressing}

// Get the code for step 6
await b // promise.then(function b4() {console.log(a); console.log('after1'); })Microtask queue: [B4]Copy the code

15. Clear the microtask queue again

Microtask queue: []/ / to emptyThe b4 callback function puts the execution stack to execute// Print Promise {
      
       }, after1
      

Copy the code

This is a big pity. We will await await a Promise, and await a will never wait until the Promise {depressing} is fulfilled. Then the corresponding callback will not be called and will not be added to the queue, so there will be no subsequent queue clearing and callback function execution

It actually looks like this:await a // promise.then(() => {resolve(true); console.log('after2'); })
    
Copy the code
  • Combined with step by step analysis at the beginning of the print sequence given results, probably can understand the principle

Talk about “await” here

So let’s change the topic above

. I'm going to omit the code a =new Promise(async (resolve, reject) => {
    console.log(a);
    await console.log(b); Promise.resolve(console.log(b)).then(() => {console.log(a); console.log('after1')})
    console.log(a);
    console.log('after1');
    await a
    resolve(true);
    console.log('after2');
});

console.log(a); // Promise {
      
       } if the a assignment is printed here, it is successful
      

console.log('end');
Copy the code

The printed result becomes

promise1
undefined
Promise {<pending>}
end
promise2
Promise {<pending>}
after1
promise3
promise4
Copy the code

Under the analysis of

  • Resolve returns a new Promise object after the b3 callback succeeds. Resolve returns a new Promise object

  • The b in promise.resolve (console.log(b)) will be immediately printed ‘Promise {pending}’ as soon as the sync code reaches this point.

  • Resolve (console.log(b)) => {console.log(a); Console. log(‘after1’)} is added to the microtask queue

// The microtask queue looks like this when we get to step 3 aboveMicrotask queue: [B1]// Now that the code has been changed, the microtask queue looks like this after step 3Microtask queue: [b1, () => {console.log(a);console.log('after1')}]
Copy the code
  • The microtask queue is emptied after the subsequent synchronization code is executed
Microtask queue: [b1, () => {console.log(a);console.log('after1')}] microtask queue: []/ / to empty

// First in, first outB1 callback into the stack execution, () => {console.log(a);console.log('after1'} into the execution stack executionCopy the code
  • This is why ‘a: Promise {pending}’ and ‘after1’ print after promise2 and before promise3 and promise4
() = > {console.log(a);console.log('after1'} this callback is executed in sequence with the B1 callbackCopy the code

The above is my own personal analysis, not all descriptions are correct, if there are mistakes or different views, welcome to point out and discuss in the comments section