javascript
事件循环是执行栈,还有微任务和宏任务之间的关联,看了很多网上的文章,大多对事件循环秉持的观点如下:
执行栈执行同步代码,宏任务和微任务执行异步代码。执行栈中同步代码执行完毕之后,再执行微任务队列,等微任务队列执行完毕后,再执行宏任务队列,然后再执行微任务对列循环往复执行。
先不说改观点是对是错,先看宏任务和微任务既然都是执行异步代码的消息队列,两者又有什么区别:
- 宏任务
macrotask
:script
(整体代码),setTimeout
,setInterval
,setImmediate
,I/O
,UI rendering
。 - 微任务
microtask
:process.nextTick
,Promise
,Object.observe
(已废弃)。
宏任务中有script
(整体代码),这个就比较疑惑了?如果script
(整体代码)是宏任务的话,那肯定是宏任务先执行,因为script
(整体代码)在一开始就会执行。在之前的观点中明明是微任务先执行,然后再执行宏任务,这个就比较矛盾了。所以以上的观点是值得商榷的,事件循环从script
(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的微任务。当所有可执行的微任务执行完毕之后。循环再次从宏任务开始,找到其中一个任务队列执行完毕,然后再执行所有的微任务,这样一直循环下去。
看一道经典的面试题来加深事件循环的理解:
<script>
let timer1 = setTimeout(() => console.log('setTimeout1'), 0); //1宏任务
let timer2 = setTimeout(() => { //2宏任务
console.log('setTimeout2');
let promise2 = Promise.resolve().then(() => { //2微任务
console.log('promise3');
let promise3 = Promise.resolve().then(() => { //3微任务
console.log('promise4');
});
console.log(5);
});
let timer4 = setTimeout(() => console.log('setTimeout4'), 0); //4宏任务
}, 0);
let timer3 = setTimeout(() => console.log('setTimeout3'), 0); //3宏任务
console.log("console1")
let promise1 = Promise.resolve().then(() => { //1微任务
console.log('promise1');
});
</script>
- 开始
script
整体代码执行宏任务。 -
timer1
,timer2
,timer3
是异步代码,依次进入宏任务队列等待执行。 - 同步代码入执行栈,输出
console1
。 - 接下来是
promise1
,进入微任务队列并执行,输出promise1
。 - 第一轮宏任务循环结束,开始第二轮宏任务,
timer1
执行并输出setTimeout1
。 - 第二轮宏任务结束,开始第三轮宏任务,执行
timer2
,代码如下:
let timer2 = setTimeout(() => { //2宏任务
console.log('setTimeout2');
let promise2 = Promise.resolve().then(() => { //2微任务
console.log('promise3');
let promise3 = Promise.resolve().then(() => { //3微任务
console.log('promise4');
});
console.log(5);
});
let timer4 = setTimeout(() => console.log('setTimeout4'), 0); //4宏任务
}, 0);
- 同步代码入执行栈,执行并输出
setTimeout2
。 -
promise2
进入微任务队列开始执行,执行同步代码,依次输出promise3
,5
。 -
promise3
进入微任务队列开始执行,输出promise4
,要注意的是当结束一轮宏任务之后,必须执行当前所有的微任务,才能进入下一轮宏任务。 - 然后发现该轮宏任务循环还有个
timer4
,排入宏任务队列。 - 因为队列是先进先出,
timer3
比timer4
先进入宏任务队列,所以先执行timer3
,输出setTimeout3
。 - 最后执行
timer4
,输出setTimeout4
。
网友评论