在阅读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?
我觉的主要的点,在于立即执行和稍后执行 ,then中的代码显然是立即执行的,然后才轮到计时器中的代码