目录:
  • 执行栈&事件队列
  • 宏任务&微任务
  • 运行机制
  • Node和浏览器事件循环的区别

执行栈&事件队列:

由于JS是单线程,所以后一个任务需要等前面执行完后才可以执行,即所有的任务都要排队。在JavaScript中,无非就是就两种任务:

  • 同步任务:进入主线程的执行栈顺序执行。
  • 异步任务:进入事件队列等待执行。

宏任务&微任务:

为什么要区分宏任务和微任务?
其实就是规定异步任务的优先级。

  • 宏任务:setIntervalsetTimeoutscript整体代码、IO
  • 微任务:Promise.then()

事件循环运行机制:

  • 执行宏任务,在这过程中遇到微任务加入到微任务的任务队列中。
  • 执行当前微任务队列中的所有微任务。
  • 继续从事件队列中接管下个宏任务。

这种循环往复的方式就是事件循环。

实例:

点击查看代码
setTimeout(function() {
    console.log('setTimeout');
})
new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})
console.log('console');

执行顺序:

  • 先执行宏任务(整个代码),将setTimeout注册到宏任务;遇到呢我new Promise立即执行宏任务打印promise;继续执行宏任务打印console
  • 宏任务执行完毕,开始执行微任务,当前微任务队列没有微任务,从消息队列中接管下个宏任务。
  • 执行setTimeout宏任务,打印setTimeout

所以执行顺序是:promise----->console---->setTimeout

点击查看代码
 setTimeout(() => {
 console.log('timer1')
 Promise.resolve().then(function () {
 console.log('promise1')
 })
 }, 0)
 setTimeout(() => {
 console.log('timer2')
 Promise.resolve().then(function () {
 console.log('promise2')
 })
 }, 0)

执行顺序:

  • 执行宏任务(整个代码),先将第一个setTimeout注册到宏任务队列,再将第二个setTimeout注册到宏任务队列,当前宏任务执行完毕。
  • 开始执行当前微任务,当前队列没有微任务,继续接管下一个宏任务。
  • 开始执行当前宏任务,执行第一个setTimeout,打印timer1,将Promise注册到微任务队列,当前宏任务执行完毕。
  • 开始执行当前微任务,执行Promise,打印promise1,当前微任务执行完毕。
  • 开始接管下一个宏任务,执行第二个setTimeout,打印timer2,将Promise注册到微任务队列,当前宏任务执行完毕。
  • 开始执行当前微任务,执行Promise,打印promise2,当前微任务执行完毕。

所以执行顺序是:timer1---->promise1----->timer2----->promise2

Node.js中的事件循环:

在Node.js的V10以下的事件循环是由libuv实现,V11以上和浏览器相同。

在Node10之前的执行顺序:

  • 执行完一个阶段的所有内容。
  • 执行完nextTick队列里面的内容(process.nextTick独立于事件循环,优先执行)
  • 然后执行完微任务队列的内容
    例如:
点击查看代码
 setTimeout(() => {
 console.log('timer1')
 Promise.resolve().then(function () {
 console.log('promise1')
 })
 }, 0)
 setTimeout(() => {
 console.log('timer2')
 Promise.resolve().then(function () {
 console.log('promise2')
 })
 }, 0)
  • 首先执行宏任务,将两个timer放入timer队列。
  • 进入times阶段,执行第一个打印timer1,并将promise1放入微任务队列。
  • 执行timer2,将promise2放入微任务队列。
  • 执行微任务队列,依次打印promise1promise2

所以执行顺序是:timer1---->timer2---->promise1---->promise2

更多内容请看:IFTS