在阅读Understanding the Node.js Event Loop这篇文章的时候,对文中一段实例代码的结果感到困扰。代码如下:
console.log('script start')
const interval = setInterval(() => {
console.log('setInterval')
}, 0)
setTimeout(() => {
console.log('setTimeout 1')
Promise.resolve().then(() => {
console.log('promise 3')
}).then(() => {
console.log('promise 4')
}).then(() => {
setTimeout(() => {
console.log('setTimeout 2')
Promise.resolve().then(() => {
console.log('promise 5')
}).then(() => {
console.log('promise 6')
}).then(() => {
clearInterval(interval)
})
}, 0)
})
}, 0)
Promise.resolve().then(() => {
console.log('promise 1')
}).then(() => {
console.log('promise 2')
})
先说下这段代码运行的结果是:
script start
promise1
promise2
setInterval
setTimeout1
promise3
promise4
setInterval
setTimeout2
setInterval
promise5
promise6
对这个结果有两个疑问:
按照文中的解释,刚开始的时候:
setInterval 加入 macrotask 队列;
setTimeout 1 加入 macrotask 队列;
Promise.resolve 1 中,两个 then 加入 microtask 队列;
调用栈变空,microtask 执行。
Macrotask queue: setInterval, setTimeout 1
我的问题是,在其他文章中看到这样一段话:
在单次的迭代中,event loop首先检查macrotask队列,如果有一个macrotask等待执行,那么执行该任务。当该任务执行完毕后(或者macrotask队列为空),event loop继续执行microtask队列。如果microtask队列有等待执行的任务,那么event loop就一直取出任务执行知道microtask为空。
那么为什么运行的结果先是显示了promise1和promise2呢?这时候macrotask队列不是空的啊,为什么没有先显示setInterval?为什么刚开始直接从microtask队列开始执行?
第二个问题是在显示了promise3和promise4之后,文中解释这时队列的情况是:
microtask 队列为空,setInteval 回调执行,另一个 setInterval 加入 macrotask 队列,正好位于 setTimeout 2 之后;
Macrotask queue: setTimeout 2, setInteval
setTimeout 2 回调执行,promise 5 和 promise 6 加入 microtask 队列;
为什么结果是显示setInterval,然后setTimeout2,然后setInterval呢?我的理解是在显示了setTimeout2之后就应该紧接着执行microtask队列啊,也就是我觉得那部分应该是setInterval然后是setTimeout再然后是promise5,promise6,结果中为什么多了个setInterval?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
我觉的主要的点,在于立即执行和稍后执行 ,then中的代码显然是立即执行的,然后才轮到计时器中的代码
看这篇文章
第一个问题:首先要理解eventloop,事件循环从检测macrotask queue开始,最开始的时候,队列里面是js主线程,因此先输出script start。随后有setInterval和setTimeout,这个两个都是macrotask的实现,因此会将这两个定时任务插入到macrotask queue中,接着是Promise,Promise是microtask的实现,因此插入到microtask queue中,至此,作为js主线程的macrotask执行完毕。而我们知道,macrotask队列在一次循环中只取出一个task执行,所以第一个js主线程的microtask执行完之后,紧接着会判断microtask是否是空的,如果不是空的就会取出其中所有的task来执行,所以紧接着是logout promise1 promise2。。。后面的问题可以根据我前面说到的来类推了