EventLoop在浏览器与NodeJS的区别

398 阅读1分钟

结论

  • 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,此刻微任务队列什么都没有。

image.png

如果是 NodeJS版本 <= 10下, 在执行A任务的时候产生了微任务W,A任务执行完毕,那么会继续执行B,B执行完成之后再去执行微任务。 而 node >= 11 && 浏览器 执行A任务,产生了微任务,A执行完之后要去执行微任务。

image.png

image.png