JS把异步任务分为宏任务与微任务。

  • 在ES5之后,JavaScript引入了Promise,这样不需要浏览器,JavaScript引擎自身也能够发起异步任务了。

宏任务由宿主(浏览器、Node)发起

任务(代码) 宏任务 环境
script 宏任务 浏览器
事件 宏任务 浏览器
网络请求(Ajax/Fetch) 宏任务 浏览器
setTimeout()/setInterval() 宏任务 浏览器

微任务JS引擎发起的任务

任务(代码) 微任务 环境
Promise的then 微任务 JS引擎
nextTick 微任务 JS引擎
await右结合和下方的代码 微任务 JS引擎

Promise本身同步,then/catch的回调函数是异步的

代码分类

  1. 同步代码(js执行栈/回调栈)

  2. 微任务的异步代码(js引擎)

    1. process.nextTick (node)
    2. Promise.then catch()
    3. Async/Await
    4. Object.observe
  3. 宏任务的异步代码(宿主环境)

    1. script
    2. setTimeout/setInterval
    3. setImmediate
    4. IO

运行机制

运行顺序:同步>微任务>宏任务

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。

  • 同步代码先执行完
  • 立即执行当前微任务队列中的所有微任务(依次执行)
  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

面试题目讲解可以参考视频:https://www.bilibili.com/video/BV1G84y1B7hZ?vd_source=5053a6dbc1b42e83bb14303fbfead9a2