任务队列

82 阅读1分钟

微任务是在宏任务里执行的,只有把一个宏任务里的所有微任务都执行完,才会开始下一个宏任务,这个过程就叫Event-loop

  • 宏任务包括:I/O、setTimeout、setInterval、setImmediate、requestAnimationFrame(这个意思是重绘,每个浏览器重绘的方式都是不一样的,和setTimeout在一起的时候,不一定谁先执行,完全取决于浏览器)
  • 微任务包括:process.nextTick、MutationObserver、Promise.then catch finally, promise在then/catch/finally前,都是同步执行,await后面的语句也是微任务
async function async1() {
  console.log('async1 start')
  await async2()
  console.log('async1 end')
}
async function async2() {
  console.log('async2')
}
console.log('script start')
setTimeout(function () {
  console.log('setTimeout')
}, 0)
async1()
new Promise(function (resolve) {
  console.log('promise1')
  resolve()
}).then(function () {
  console.log('promise2')
})
console.log('script end')

执行步骤如下:

  1. 整体 script 作为第一个宏任务进入主线程,代码自上而下执行,执行同步代码,输出 script start
  2. 遇到 setTimeout,加入到宏任务队列
  3. 执行 async1(),输出async1 start;然后遇到await async2(),await 实际上是让出线程的标志,首先执行 async2(),输出async2;把 async2() 后面的代码console.log('async1 end')加入微任务队列中,跳出整个 async 函数。(async 和 await 本身就是 promise+generator 的语法糖。所以 await 后面的代码是微任务。)
  4. 继续执行,遇到 new Promise,输出promise1,把.then()之后的代码加入到微任务队列中
  5. 继续往下执行,输出script end。接着读取微任务队列,输出async1 end,promise2,执行完本轮的宏任务。继续执行下一轮宏任务的代码,输出setTimeout