题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| Promise.resolve() .then(() => { console.log(0); setTimeout(() => { 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); }) .then(() => { console.log(8); });
|
答:
1 2 3 4 5 6 7 8 9 10 11
| 0; 1; 2; 3; 4; 5; 6; 7; 8; 宏任务;
|
解析:
| return Promise.resolve(4)
会产生一个叫 job 的函数,等到当前执行栈为空的时候会去执行
| 微任务的执行中生成了微任务,那么会继续执行微任务,直到微任务队列为空。
- 宏任务队列 1,执行
Promise.resolve()
- 遇到
then()
回调,往微任务队列推入以下代码:
1 2 3 4 5 6 7
|
console.log(0); setTimeout(() => { console.log("宏任务"); }, 0); return Promise.resolve(4);
|
- 仍然在当前宏任务往下执行,执行第二个
Promise.resolve()
- 遇到
then()
回调,往微任务队列推入以下代码:
所以此时微任务队列里有两个代码块待执行。队列就是先进先出的原则
1 2 3 4 5 6 7 8 9
| console.log(0); setTimeout(() => { console.log("宏任务"); }, 0); return Promise.resolve(4);
console.log(1);
|
- 此时代码模块里的宏任务都已经执行完了,开始捞取微任务到执行栈中执行。队列里第一个出来的也就是代码:
1 2 3 4 5
| console.log(0); setTimeout(() => { console.log("宏任务"); }, 0); return Promise.resolve(4);
|
输出 0。
注册一个 job,当执行栈为空的时候,job 进入队列。此时执行栈并不为空。A 出栈 B 入栈
6.
输出 1。then 的回调推入微任务队列。B 出栈。执行栈为空。job 也进入微任务队列
函数是:
此时的微任务队列就有两个函数
1 2 3 4 5 6 7 8 9
| .then(() => { console.log(2); })
(4) => { this.resolvePromise(promise2, 4, resolve, reject); };
|
- 输出 2 将它的回调函数推入微任务队列
1 2 3
| .then(() => { console.log(3); })
|
再去执行
1 2 3
| (4) => { this.resolvePromise(promise2, 4, resolve, reject); };
|
这个函数会将
1 2 3
| (res) => { console.log(res); };
|
推入微任务队列
- 输出 3 和 4
输出 3 的回调再次推入微任务
1 2 3
| .then(() => { console.log(5); })
|
输出 5
后续输出原理相同,输出 6,7,8
此时没有回调微任务进栈了,开始清空宏任务队列,也就是 setTimeout,输出宏任务