理解Promise的执行顺序,需要一些背景知识作为前提:
1:每一个当下,正在被执行的JS代码是放在JS的主线程(我们叫JS Stack)的。同步的代码会按照代码顺序依次放入JS Stack,然后按照放入的顺序依次执行。
2:异步的代码会被放入Macrotask或者Microtask,promise属于Microrask。这篇文章,我们先忽略Macrotask。
3:异步的代码一定是要等到同步的代码执行完了才执行。也就是说,直到JS Stack为空,Microtask里面的代码才会被提到JS Stack,然后被执行。
4:new Promise()和.then()方法属于同步代码。
5:.then(resolveCallback, rejectCallback)里面的resolveCallback, rejectCallback的执行属于异步代码,会被放入Microtask。
6: resolve()被调用会起到2点作用:
1:Promise由pending状态变为resolved
2:遍历这个promise上所注册的所有的resolveCallback方法,依次加入Microtask。
7: .then()只是注册callback方法,并不会把callback方法加入Microtask(参考上面的第6点)。
好的,有了以上的7点前提知识,我们接下来看2个例子,运用以上的7点来分析promise的执行顺序。
第一个例子:
new Promise((resolve, reject)=> {
resolve(1);
Promise.resolve().then(()=>{
console.log(2);
})
}).then((t)=>{console.log(t)});
console.log(3);
以上代码的正确输出结果为:3,2,1
如果你的答案是错误的,就跟着我一步一步来分析为什么是3,2,1:
Step1:new Promise(...)
运用上面的第4点知识,new Promise()是同步代码,所以会被立即执行。也就是会去执行它的executor function。我们把这个外层的promise叫做outerPromise。
Step 2: resolve(1)
运用第6大点的第1小点知识,此时最外层的这个promise由pending状态变为resolved状态。但是,因为我们现在还没有执行到最外层的then()方法,所以此刻最外层的promise上并没有注册任何的callback方法,所以,也就无法把
(t)=>{console.log(t)}
这个callback放入Microtask里面。
这一步执行完:
JS Stack: [outerPromise-executor-function]
Microtask: []
Step3:Promise.resolve().then(...)
这里是直接创建了一个应是resolved状态的promise,我们把它叫做innerPromise。运用第4点知识,then()方法是被立即执行,再运用第6点知识,这一步代码执行之后,innerPromise的这个callback方法会被加入到Microtask。这块代码执行完之后,outerPromise-executor-function也就执行完了,所以这一步之后的状态是:
JS Stack: []
Microtask: [innerPromise-callback]
Step4: .then((t)=>{console.log(t)})
终于执行到了outerPromise的then()方法,因为outerPromsie已经是resolved的了,所以这个callback方法会被立即加入MicroTask。所以,这步执行完之后,我们的执行栈的状态是:
JS Stack: []
Microtask: [innerPromise-callback,outerPromise-callback]
Step5: console.log(3)
因为这行是同步代码,此刻JS Stack又是为空,所以这行代码会被立刻放入JS Stack且执行,所以我们得到结果:
打印结果:3
这一步执行完之后,我们的运行栈状态为:
JS Stack: []
Microtask: [innerPromise-callback,outerPromise-callback]
Step6: 把innerPromise-callback从Microtask提到JS Stack且执行
因为此刻JS Stack为空,且安装先入先出的顺序,innerPromise-callback就被放入JS Stack且执行。之后,我们运行栈状态为:
JS Stack: []
Microtask: [outerPromise-callback]
打印结果:3,2
Step6: 把outerPromise-callback从Microtask提到JS Stack且执行
类似地,outerPromise-callback被提入到JS Stack且执行。至此,我们的所有代码都执行完了,最终得到结果:
JS Stack: []
Microtask: []
打印结果:3,2,1
以上就是,为什么打印结果为3,2,1的分析过程。
为了验证真的理解了整个机制,下面我们对以上代码做一点修改:
new Promise((resolve, reject)=>{
Promise.resolve().then(()=>{
resolve(1);
Promise.resolve().then(()=>{console.log(2)})
})
}).then((value)=>{console.log(value)});
console.log(3);
那这段代码的输出结果又是什么呢?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。