Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

JS事件循环:宏任务和微任务

介绍

JS是单线程的,执行任务时,会按照顺序执行任务,而JS中依然存在异步任务,比如定时器、ajax、promise、setTimeout、setInterval、fetch、webSocket等等。
JS为了实现这些异步任务,使用了事件循环这一机制。

事件循环

JS 的运行时是多线程的,当 JS 需要执行异步任务时,浏览器会另外启动一个线程去执行该任务。常见的线程有定时器线程和 HTTP 请求线程等,这些线程会与 JS 的主线程进行通信,处理对应任务。
在事件循环中,当有任务触发后,被触发的任务会按顺序暂时存在一个队列中,待 JS 的同步任务执行完成后,会从这个队列中取出要处理的事件并进行处理。
任务分为两种类型:微任务和宏任务。

微任务

在 JS 中,微任务会优先于宏任务执行。这意味着在当前任务执行结束后,所有微任务都会被立即执行,而宏任务只有在所有微任务执行完毕后才会执行。这种执行顺序保证了微任务的优先级,可以避免一些问题的出现,比如处理 Promise 对象时可能会出现的竞态条件,微任务可以保证执行时机的预测性。
常见的微任务有:

  1. Promise
  2. nextTick

宏任务

宏任务在当前任务与微任务结束后才会执行的,这意味着可以将一些耗时的操作放入宏任务队列中,从而避免阻塞当前任务的执行。通常是依赖运行时其他线程处理的任务。比如,将请求放入 HTTP 请求线程,等待 HTTP 请求线程响应的同时依旧继续执行其他任务。
常见的宏任务有:

  1. setTimeout
  2. fetch
  3. xhr

事件循环执行顺序

  1. 首先执行当前代码(同步任务),直到遇到第一个宏任务或微任务。
  2. 如果遇到微任务,则将它添加到微任务队列中,继续执行同步任务。
  3. 如果遇到宏任务,则将它添加到宏任务队列中,继续执行同步任务。
  4. 当前任务执行完毕后,JavaScript 引擎会先执行所有微任务队列中的任务,直到微任务队列为空。
  5. 然后执行宏任务队列中的第一个任务,直到宏任务队列为空。

参考资料

mdn 事件循环
web前端知识:js中的微任务和宏任务
JS事件循环Event Loop,看这篇就够了

关于本人

HaiYao的博客
Git主页

评论