I saw this problem in an exchange group ———- on May 28, 2021.6.27. I also saw this problem in Zhihu link, which was explained more clearly in the first praise. The following is the exploration process at that time


The problem

        Promise.resolve().then(() = > {
            console.log(0);
            return Promise.resolve(4);
        }).then((res) = > {
            console.log(res)
        })

        Promise.resolve().then(() = > {
            console.log(1);
        }).then(() = > {
            console.log(2);
        }).then(() = > {
            console.log(3);
        }).then(() = > {
            console.log(5);
        }).then(() = > {
            console.log(6);
        }).then(() = > {
            console.log(7);
        })
Copy the code

The answer:We need to know exactly how promise works

Explore the course

— Time 2021.6.22 review promise source code, still do not get how to answer the idea is as follows

  • Then1 internal callback, which is put into the microqueue because it was preceded by the successful P object given

  • Then2 will execute resolve(v) or reject(r) according to then1’s internal callbacks, since THEN1 returns a pending P1 object, then2 will place the callbacks in P1’s callbacks array. Within resolve(v) or Reject (r), processing callbacks are added to the microqueue

  • Since then3 gets a successful P object, all subsequent THEN3’s can only get a pending object, so when executing synchronous code, only then3’s callback will be actively placed on the micro queue, and then all subsequent THEN3’s will be placed on the corresponding P callbacks

  • When the synchronization ends, only then1 and THEN3 callbacks go into the microqueue. The rest are in the callbacks

  • The first time the microqueue executes then1’s callback, printing 0, and getting a p_SUCCESS (self-named) object with a success value of 4

  • Then1 gets the successful p object inside, execute resolve(p_success), and place the callbacks handler with then2’s callback on the new microqueue

  • Then2, there is no matter, synchronous asynchronous has nothing to do with him

  • Skip to then3’s callback, execute, print 1, and get a successful p object with the value undefined

  • Inside then3, get the success P object, execute resolve(p), and place the callbacks handler with then4’s callback on the new microqueue

Here is stuck, I don’t know why the output output will continue after 1 2 and 3, and jump into 4, 0 after clearly inside a micro queue, is only the output 1, 0 after the output 4 callback in the queue, but cannot perform the output of the 4 output after 1, 2, but the output

It is too difficult, and the source code teaching basically uses setTimeout to simulate the promise. I use queueMicrotask to simulate the original promise, but it does make a point

By writing promises by hand, I learned that new promises () aren’t executed asynchronously,

Promise.resolve() is also not executed asynchronously; all that promises are executed asynchronously is the callback function in then, the argument

Also, the THEN method is not all asynchronous, only the callback part is asynchronous, and the step that returns a new Promise is not asynchronous

However, the state of the promise is pending until asynchronous execution is complete, and the state is changed by a closure waiting for asynchronous execution to complete

In the promise code, only the callbacks in the THEN are asynchronous, and everything else is synchronous. When processing asynchronously, the then may not get the result to execute the callback, and the callback will be saved to the instance object, but when the closure gets the result, it will queue up the callback function asynchronously.

Then registration only returns a stateful promise object from the previous THEN. If you continue the then and there is no result, other synchronization code will be executed.The article links However, I have reservations, because WHEN I debug, I let an object for each then, and you can see that each object is actually generated but in pending state, as shown below

let p1 = Promise
    .resolve()

let p2 = p1.then(() = > {
    console.log(0);
    return p = Promise
        .resolve(4);
})
let p3 = p2.then((res) = > {
    console.log(res)
})

let p4 = Promise
    .resolve()
let p5 = p4.then(() = > {
    console.log(1);
})
let p6 = p5.then(() = > {
    console.log(2);
})
let p7 = p6.then(() = > {
    console.log(3);
})
let p8 = p7.then(() = > {
    console.log(5);
})
let p9 = p8.then(() = > {
    console.log(6);
})
let p91 = p9.then(() = > {
    console.log(7);
})
Copy the code

I’ll keep it. I can’t so far. I’ve been thinking about it for two days

Important reference

—–2021.6.27, found the answer in the teaching video of b station, link belowHungry people valley front promise teaching video 2p 13 minutes As shown in the picture, teacher Fang said that the then method is a black box, and it is better not to explore the principle, because the promise implementer can change the internal rules at any time, just like below Node11, micro-task does not support queue-cutting. There is micro-task 3 in micro-task 1, so it will also be followed by micro-task 2, but the rules were changed later. Microtasks can be done instantly, by which he means just remember the rules, and the promiseA+ specification doesn’t write that either. (In fact, I don’t agree with this point of view. I prefer to know the internal principle, which will improve me a lot. Of course, Teacher Fang is from the perspective of an educator and trainer.

Get to the point

Then I will follow teacher Fang’s ideas, in this ordinary chain call case, the next and second promise callback execution order is one up and one down alternately

Resolve (3.5) return promise.resolve (3.5) Resolve (), the Promise’s next callback will be executed two times later than it should have been. Resolve (); resolve (); return promise.resolve ()

So the order changed from 12345678910 to 1234 > 6 >8 >5 >10 >7 >9

Return promise.resolve () = 7 >12 >9 >14 >16Note, however, that this applies to a function that returns promise.resolve (). If you just write a return instead of return promise.resolve (), this rule does not apply, so look at the code below

        Promise.resolve().then(() = > {
            console.log(0);
            return 
        }).then((res) = > {
            console.log(res)
        })

        Promise.resolve().then(() = > {
            console.log(1);
        }).then(() = > {
            console.log(2);
        }).then(() = > {
            console.log(3);
        }).then(() = > {
            console.log(5);
        }).then(() = > {
            console.log(6);
        }).then(() = > {
            console.log(7);
        })
Copy the code

Will be outputBecause only a return cannot be applied to the previous rule, it will still go up and down

Similarly, in the following example, resolve also works, similar to returning a result, because the principle of promise is to return a promise object, and return is based on the following object category, Resolve simply returns a successful promise object

        new Promise((resolve, reject) = > {
            console.log(0);
            resolve(Promise.resolve())
        }).then(() = > {
            console.log(4);
        })

        Promise.resolve().then(() = > {
            console.log(1);
        }).then(() = > {
            console.log(2);
        }).then(() = > {
            console.log(3);
        }).then(() = > {
            console.log(5);
        }).then(() = > {
            console.log(6);
        }).then(() = > {
            console.log(7);
        })
Copy the code

Regular summary

Resolve (), reject (Promise. Resolve ()), reject (Promise. Resolve ()), reject (Promise. As long as it’s in a block of code that returns a successful promise object, such as one more promise.resolve (), the promise.resolve () operation blocks two subsequent callbacks, and then one more, Or just new Promise (excutor), resolve (value) will block twice

Here’s what I’m going to do

    Promise.resolve().then(() => {
        console.log(0);
        return Promise.resolve(4);
    }).then((res) => {
        console.log(res)
    })
    
Copy the code

Changed to

  return new Promise((resolve, reject) => {
    resolve(4)
  })
    
Copy the code

The output is still 01234567

    Promise.resolve().then(() = > {
      console.log(0);
      return new Promise((resolve, reject) = > {
        resolve(4)
      })
    }).then((res) = > {
      console.log(res)
    })

    Promise.resolve().then(() = > {
      console.log(1);
    }).then(() = > {
      console.log(2);
    }).then(() = > {
      console.log(3);
    }).then(() = > {
      console.log(5);
    }).then(() = > {
      console.log(6);
    }).then(() = > {
      console.log(7);
    })` `See zhihu's answer in the video, this is not only according to the law, but according to the principle, know the operation logic of promise's resolve, Know why is this [zhihu] (https://www.zhihu.com/question/430549238/answer/1624864911)! [insert picture description here] (https://img-blog.csdnimg.cn/202106270955436.png?x-oss-process=image/watermark, type_ZmFuZ3poZW5naGVpdGk, shado W_10 text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZvaWNldQ = =, size_16 color_FFFFFF, t_70) summary of * * * * * * the resolve of the parameters for the Promise, Two microtask to additional consumption, is the first microtask PromiseResolveThenableJob specification requirements; The second microTask function synchronizes the state of a resolvedPromise to P0. * * the first great bosses write very detailed [zhihu link] (https://www.zhihu.com/question/430549238/answer/1624864911)! [insert picture description here] (https://img-blog.csdnimg.cn/2021062710051321.png?x-oss-process=image/watermark, type_ZmFuZ3poZW5naGVpdGk, shad Ow_10 text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZvaWNldQ = =, size_16 color_FFFFFF, t_70) but the source code is also likely to become, in node6 7 8, 10, 11 and other versions are the output, Node9 is output next to node9, but node9 is output next to node9` `javascript
        Promise.resolve().then(() = > {
            console.log(0);
        }).then((res) = > {
            console.log(res)
        })

        Promise.resolve().then(() = > {
            console.log(1);
        }).then(() = > {
            console.log(2);
        }).then(() = > {
            console.log(3);
        }).then(() = > {
            console.log(5);
        }).then(() = > {
            console.log(6);
        }).then(() = > {
            console.log(7);
        })
Copy the code

Answer: 0 1 undefined 2 3 5 6 7This will change the position of undefined to 4 and the two callbacks after 1 to 0, 1, 2, 3, 4 (undefined), 5, 6, 7

        Promise.resolve().then(() = > {
            console.log(0);
            return Promise.resolve(4);
        }).then((res) = > {
            console.log(res)
        })

        Promise.resolve().then(() = > {
            console.log(1);
        }).then(() = > {
            console.log(2);
        }).then(() = > {
            console.log(3);
        }).then(() = > {
            console.log(5);
        }).then(() = > {
            console.log(6);
        }).then(() = > {
            console.log(7);
        })
Copy the code