Is resolving a promise an asychronous process?

2019-08-06 02:55发布

问题:

I am sure that all the codes below, except resolve(Promise.resolve(p2)), are synchronous. So I expect the result is p2 first since the p2.then run first. However p1 comes out first in console.

MDN has nothing related to the question. Does the spec has some details? Can someone make it clear step by step what happens in resolving a promise?

Chrome v60.0.3112.113

My code is:

var p1 = new Promise(function(resolve, reject){
  resolve("p1");
});

var p2 = new Promise(function(resolve, reject){
  //resolve("p2");
  var tempP = Promise.resolve("p2"); // for better description in discussion
  resolve(tempP);
});

p2.then(function(value){
  console.log(value)
})
p1.then(function(value){
  console.log(value);
});

回答1:

I am sure that all the codes below, except resolve(Promise.resolve(p2)), are synchronous.

No. then callbacks are never called synchronously, they're always asynchronous (and that's good). That means their relative order is indeterminate, and depends on when the respective promise was fulfilled. If you ever care about the order of callbacks, make it explicit by chaining the promises onto each other.

The order of fulfillment in your example depends on the value that you resolved the promises with. Notice that the new Promise callback and therefore your resolve are synchronous, in both p1 and p2. Every resolution is put into a queue - at least with native ES6 promises that you appear to be using. The difference is that your p2 is resolved with Promise.resolve("p2"), which will resolve p2 with the result of that other promise - which is put back onto the queue again. Therefore the fulfillment of p1 happens first, and the callback is called before the fulfillment callback of p2.

So what happens step-by-step is

  1. The new Promise calls the constructor callback, which in turn
  2. resolves the new promise with the value "p1" - fulfilling it
  3. The new Promise returns and the value is assigned to p1.
  4. The new Promise calls the constructor callback, which in turn
  5. constructs another promise fulfilled with the value "p2"
  6. and resolves the new promise with it - which adds another resolve as a callback for when that promise completes
  7. The inner promise schedules that callback as it is already is fulfilled
  8. The new Promise returns and the value is assigned to p2.
  9. The p2.then is called and registers the fulfillment callback
  10. The p1.then is called and schedules the fulfillment callback, as p1 is already fulfilled

After that, asynchronously:

  1. the inner promise's callback is called and resolves p2 with the value "p2 - fulfilling it and scheduling its registered callbacks
  2. the p1 callback is called and logs "p1"
  3. the p2 callback is called and logs "p2"


回答2:

This is the expected behavior.

Promise.resolve() returns a promise which is guaranteed to be asynchronous. So the value it returns will always resolve at the earliest on the next event loop after it is called. So in this case what happens is:

P2 returns a promise
P1 returns a promise

Next loop

P2 calls then() which resolves to a new promise that's scheduled for the next loop
P1 calls then() callback which resolves to a value which is printed

Next loop

P2's returned promise resolves and is printed



回答3:

Both p1 and p2 are async, as you are creating a Promise. New Promise() creates a new promise, and once it is created the following code is executed, but execution inside the Promise is done later (or at the same time; async).

p2.then is not executed before p1.then. The .then function is executed, once the promise resolves, and p1 resolves before p2



回答4:

You code above :

var p2 = new Promise(function(resolve, reject){
    resolve(Promise.resolve("p2"));
});

Is equivalent to doing :

var p2 = new Promise(function(resolve, reject) {
    resolve(new Promise(function(resolve1, reject1) {
        resolve1("p2"); 
    }));
});

Which creates a new promise that is although immediately resolved, will be executed at the end of the call queue.