书接之前代码输出题目,
异步&事件循环
27.代码输出结果
console.log('1');
setTimeout(function () {
console.log('2');
process.nextTick(function () {
console.log('3');
})
new Promise(function (resolve) {
console.log('4');
resolve();
}).then(function () {
console.log('5')
})
})
process.nextTick(function () {
console.log('6');
})
new Promise(function (resolve) {
console.log('7');
resolve();
}).then(function () {
console.log('8')
})
setTimeout(function () {
console.log('9');
process.nextTick(function () {
console.log('10');
})
new Promise(function (resolve) {
console.log('11');
resolve();
}).then(function () {
console.log('12')
})
})
输出结果如下:
1
7
6
8
2
4
3
5
9
11
10
12
代码执行顺序如下:
(1)第一轮事件循环流程分析如下:
- 整体script作为第一个宏任务进入主线程,遇到
console.log
,输出1。 - 遇到
setTimeout
,其回调函数被分发到宏任务Event Queue中。暂且记为setTimeout1
- 遇到
process.nextTick()
,其回调函数被分发到微任务Event Queue中。记为process1
- 遇到
Promise
,new Promise
直接执行,输出7。then
被分发到微任务Event Queue中。记为then1
- 又遇到了
setTimeout
,其回调函数被分发到宏任务Event Queue中,记为setTimeout2
宏任务Event Queue |
微任务Event Queue |
setTimeout1 |
process1 |
setTimeout2 |
then |
上表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。发现了 process1
和 then1
两个微任务:
- 执行
process1
,输出 6 - 执行
then1
,输出 8
第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。
(2)第二轮时间循环从 setTimeout1
宏任务开始:
- 首先输出2。接下来遇到了
process.nextTick()
,同样将其分发到微任务Event Queue中,记为process2
new Promise
立即执行输出4,then
也分发到微任务Event Queue中,记为then2
宏任务Event Queue |
微任务Event Queue |
setTimeout2 |
process2 |
then1 |
第二轮事件循环宏任务结束,发现有 process2
和 then2
两个微任务可以执行:
- 输出3
- 输出5
第二轮事件循环结束,第二轮输出2,4,3,5。
(3)第三轮事件循环开始,此时只剩setTimeout2了,执行。
- 直接输出9。
- 将
process.nextTick()
分发到微任务Event Queue中。记为process3
- 直接执行
new Promise
,输出11。 - 将
then
分发到微任务Event Queue中,记为then3
宏任务Event Queue |
微任务Event Queue |
process3 |
|
then3 |
第三轮事件循环宏任务执行结束,执行两个微任务 process3
和 then3
- 输出10
- 输出12
第三轮事件循环结束,第三轮输出9,11,10,12。
整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。
28.代码输出结果
console.log(1)
setTimeout(() => {
console.log(2)
})
new Promise(resolve => {
console.log(3)
resolve(4)
}).then(d => console.log(d))
setTimeout(() => {
console.log(5)
new Promise(resolve => {
resolve(6)
}).then(d => console.log(d))
})
setTimeout(() => {
console.log(7)
})
console.log(8)
输出结果如下:
1
3
8
4
2
5
6
7
代码执行顺序如下:
- 首先执行script代码,打印出1;
- 遇到第一个定时器,加入到宏任务队列;
- 遇到Promise,执行代码,打印出3,遇到resolve,将其加入到微任务队列;
- 遇到第二个定时器,加入到宏任务队列;
- 遇到第三个定时器,加入到宏任务队列;
- 继续执行script代码,打印出8,第一轮执行结束;
- 执行微任务队列,打印出第一个Promise的resolve结果:4;
- 开始执行宏任务队列,执行第一个定时器,打印出2;
- 此时没有微任务,继续执行宏任务中的第二个定时器,首先打印出5,遇到Promise,首选打印出6,遇到resolve,将其加入到微任务队列;
- 执行微任务队列,打印出6;
- 执行宏任务队列中的最后一个定时器,打印出7。