一说起Promise执行顺序,你会想到啥?
“不就是老掉牙的宏任务,微任务嘛,事件循环嘛”
先来两道题,看能不能答对吧,如果你懒得复制到浏览器中运行,就跳到文章最后看答案吧👀
// 案例一
new Promise((resolve, reject)=> {
resolve(1);
Promise.resolve().then(()=>{
console.log(2);
})
}).then((t)=>{console.log(t)});
console.log(3);
// 案例二
new Promise((resolve, reject)=>{
Promise.resolve().then(()=>{
resolve(1);
Promise.resolve().then(()=>{console.log(2)})
})
}).then((value)=>{console.log(value)});
console.log(3);
怎么样,和你预想的一致嘛,如果一致,哪你可以走了,这个文章不适合你!
如果百思不得其解,那就继续往下看
执行顺序
先说一个观点
.then()是同步方法,里面的callback才是异步的
案例一执行顺序
1、new Promise(...)
new Promise是同步代码,首先执行的就是里面的回调
2、resolve(1)
此时最外层的Promise状态由pedding状态变为resolve。
注意,由于现在还没有执行到最外层的then(),所以最外层的Promise没有注册任何callback,因此(t) => console.log(t)不会放到Microtask中
3、Promise.resolve().then(...)
.then()会把里面的callback放入Microtask中,看看现在的执行栈状态
JS Stack: []
Microtask: [() => console.log(2)]
4、.then((t)=>{console.log(t)})
终于执行到最外层Promise的then方法了,此时的状态已经是resolve了,因此then里面的回掉要压入到Microtask中,此时的执行栈状态
JS Stack: []
Microtask: [() => console.log(2), (1) => console.log(1)]
5、console.log(3)
这肯定是同步了,此时JS Stack为空,因此会立即压入栈中执行,打印3
此时的执行栈状态
JS Stack: []
Microtask: [() => console.log(2), (1) => console.log(1)]
后面就是事件循环了,()=> console.log(2)压入JS Stack中并执行,执行完后又将() => conosle.log(1)压入JS Stack中并执行
所以案例一 打印 3 2 1
案例二执行顺序
1、new Promise(...)
不用说,同步执行,直接看里面的回调
2、Promise.resolve().then(...)
.then是同步的,但里面的回调是异步的,因此回调进入Microtask中,此时的执行栈状态
JS Stack: []
Microtask: [ () => {resolve(1); Promise.resolve().then(....)} ]
3、.then(...)
执行到最外层
Promise的then方法了,将回调压入Microtask中,此时的执行栈状态
JS Stack: []
Microtask: [ () => {resolve(1); Promise.resolve().then(....)}, (value) => console.log(value) ]
此时的微任务队列里面排队了两个任务,第一个是第二层Promise.then回调,第二个是第一层Promise.then回调
4、console.log(3)
同步,立即执行,打印 3,此时的执行栈状态
JS Stack: []
Microtask: [() => {resolve(1); Promise.resolve().then(....)}, (value) => console.log(value)]
5、将第二层的Promise-callback从Micotask中提升到JS Stack中
此时的执行栈状态
JS Stack: [() => {resolve(1); Promise.resolve().then(() => console.log(2))}]
Microtask: [(value) => console.log(value)]]
执行到resolve(1)时,第一层的Promise状态由pedding转为resolve
紧接着,执行Promise.resolve().then(() => console.log(2)},又将then里面的回调压入Microtask中
JS Stack: []
Microtask: [ (1) => console.log(1), () => console.log(2) ]
6、将第一层的Promise-callback从Micotask中提升到JS Stack中
此时的执行栈状态
JS Stack: [ (1) => console.log(1) ]
Microtask: [ () => console.log(2) ]
执行后打印 1
7、将第三层的Promise-callback从Micotask中提升到JS Stack中
此时执行栈状态
JS Stack: [ () => console.log(2) ]
Microtask: []
执行后打印 2
综上,案例二打印结果为 3 1 2
答案
案例一打印:3 2 1
案例二打印:3 1 2