When the parameter of Promise.resolve is a thenable object
http://es6.ruanyifeng.com/-sharpdo...
this is Mr. Ruan Yifeng"s interpretation of the Promise.resolve () parameter. When the parameter is a thenable object, the Promise.resolve method converts the object to a Promise object, and then immediately executes the then method of the thenable object.
here comes the problem:
new Promise (resolve = > {
)
resolve(1);
Promise.resolve({
then: function(resolve, reject){
console.log(2);
resolve(3)
}
}).then(t => console.log(t))
console.log(4);
}) .then (t = > console.log (t));
console.log (5);
console output: 4 5 2 1 3
convert the above code
new Promise (resolve = > {
) according to the initial understanding.
resolve(1);
new Promise(resolve=>{
console.log(2);
resolve(3)
}).then((t) => console.log(t));
console.log(4);
}) .then (t = > console.log (t));
console.log (5);
console output 2 4 5 3 1
the order is different. I was devastated to ask for answers
you have to understand two things,
The resolve of - Promise presses tasks on a stack. Depending on the implementation of the Promise specification (such as native and polyfill), some tasks will be micro-task before the end of the current event loop, and some will macro-task after the current event loop is finished, in short, it will be behind the platform code.
-
this platform code means:
Here "platform code" means engine, environment, and promise implementation code.
many people just ignore the fact that the code implemented by promise is also counted as platform code.
then look back at the example,
-
new Promise ([executor])
execute first and enter the executor function.
- the first line has already
resolve (1);
this Promise immediately transitions from the pending state to the fulfill state. This task with 1
is pushed to the stack mentioned earlier.
- continue to execute the rest of the executor code.
Promise.resolve ([object])
, this task with [object]
is pushed onto the stack.
- encountered the first
console.log (4);
.
- second
console.log (5);
.
- after running the platform code for this round, start clearing the stack.
- handles tasks with
[object]
because there is a then
method in this object, which is called directly as the new executor.
- notice that executor is synchronized. Here we immediately encounter
console.log (2)
.
- then
resolve (3)
, because the stack of this round is not finished (the bottom layer of Promise also belongs to "platform code"), this task with 3
is pushed into the stack of next round .
- handles tasks with
1
, .then (t = > console.log (t));
prints 1
.
- Stack is empty, clean up the next round of stacks immediately.
- print
3
.
- finished processing.
The
owner's interpretation of the Promise.resolve () parameter is actually correct (the Promise.resolve method converts the object to a Promise object, and then immediately executes the then method of the thenable object. ), the only object that ignores the passed-in parameters has been converted to Promise, and then the object's then method is called, which is already an asynchronous operation, that is, a microtask.
you can test the code
Promise.resolve({
then: function(resolve, reject){
console.log(2);
resolve(3)
}
})
.then(t => console.log(t))
console.log(4);
if the then method of the object is called synchronously, the output should be 2 43 , but the actual output is 4 23 ; after
has this premise, I will re-label the code and explain it with your thinking. (@ CRIMX's explanation is too professional. I will analyze it according to my personal understanding.)
the tag code is as follows:
new Promise(resolve => { //1 promise
resolve(1); //2
Promise.resolve({ //3 Promise.resolve
then: function(resolve, reject){ //4 then
console.log(2);
resolve(3) //8
}
})
.then(t => console.log(t)) //9 then1
console.log(4); // 5
})
.then(t => console.log(t)); //6 then
console.log(5); // 7
1. The code runs and starts running the parameter function (synchronization function) of the promise constructor
2. When you run to resolve (1), the state of the promise instance becomes fulfill. At this time, because the function is a synchronization function, and there is still unexecuted code, the external then function in step 6 will not be added to the microtask. It will be added only after the synchronization function (step 1) has been executed.
3. Run to Promise.resolve ([object]), change to a promise object, and then run the object then function (internal then function)
4. Run the internal then function, add it to the micro task, then continue to synchronize the function, and encounter the inner then1 function in step 9, which will not be executed until the promise decision in step 3, so the function will remain in the promise
5. Output 4
6. At this time, the synchronization function finishes running and meets the external then function. Because the external promise has been decided (step 2), this function is also added to the micro-task queue. Now the micro-task queue is listed as [internal then function, external then function]
7. Continue to execute other synchronization code and output 5
8. After the execution of the synchronization code, execute the micro-task, take out the internal then function, and output 2. Then resolve (3) (decides on the promise) and executes the inner then1 function that has not been called before.
9. Run the internal then1 function and join the micro-task queue. Now the micro-task queue is listed as [external then function, internal then1 function]. The micro-task completes
10. Call the micro task in turn, output 1, output 3.
- new Promise () takes a function argument, which is executed immediately, that is, synchronization.
- Promise's then methods are all asynchronous
- Promise.resolve () receives the thenable parameter, and calling the then method of thenable is also asynchronous.
you can look at the source code of some libraries that implement promise, which will be clearer.