结论
NodeJS 版本 >= 11之后就和浏览器保持一致NodeJS 版本 <= 10,浏览器和NodeJS 环境下,在 microtask(微任务) 任务队列的执行时机不同,有不同的效果的
看题
function test() {
setTimeout(() => {
console.log('children2')
Promise.resolve().then(() => {
console.log('children2-1')
})
}, 0)
setTimeout(() => {
console.log('children3')
Promise.resolve().then(() => {
console.log('children3-1')
})
})
}
test()
答案
// node >= 11 && 浏览器 >>
children2 children2-1 children3 children3-1
// node <= 10 >>
children2 children3 children2-1 children3-1
解析
我们就记住浏览器的EventLoop的机制就可以,如果问到在NodeJS环境下的执行是什么,我们可以来解析一下
1、在 NodeJS 版本 >= 11以及浏览器下
- 执行test函数
- 执行第一个setTimeout,放入到宏任务里面
- 执行第二个setTimeout,放入到宏任务里面
- 此刻微任务里面没有任务,那么执行宏任务,从队列的头部取出一个宏任务(第一个setTimeout)
- 打印 children2, 此刻遇见Promise的then,是微任务,放入到微任务队列里面
- 接下来我们发现微任务里面有任务了,取微任务里面的任务,打印 children2-1
- 此刻微任务里面没有任务,那么继续执行宏任务,从队列的头部取出一个宏任务(第二个setTimeout)
- 打印 children3, 此刻遇见Promise的then,是微任务,放入到微任务队列里面
- 接下来我们发现微任务里面有任务了,取微任务里面的任务,打印 children3-1
2、在 NodeJS版本 <= 10 版本下
- 执行test函数
- 执行第一个setTimeout,放入到宏任务里面
- 执行第二个setTimeout,放入到宏任务里面
- 此刻微任务里面没有任务,那么执行宏任务,从队列的头部取出一个宏任务(第一个setTimeout)
- 打印 children2, 此刻遇见Promise的then,是微任务,放入到微任务队列里面
- 注意注意!!!此刻将会继续从队列的头部取出一个宏任务(第二个setTimeout)
- 打印 children2, 此刻遇见Promise的then,是微任务,放入到微任务队列里面
- 此刻微任务就有2个任务,依次取出执行 children2-1 children3-1
大白话
它们的主要区别是执行微任务的时机是不同的,假如此刻宏任务有2个任务AB,此刻微任务队列什么都没有。
如果是 NodeJS版本 <= 10下, 在执行A任务的时候产生了微任务W,A任务执行完毕,那么会继续执行B,B执行完成之后再去执行微任务。 而 node >= 11 && 浏览器 执行A任务,产生了微任务,A执行完之后要去执行微任务。