写点什么

Web 前端入门:JavaScript 事件循环机制中的微任务与宏任务

  • 2025-06-24
    福建
  • 本文字数:1700 字

    阅读完需:约 6 分钟

JS 是单线程语言。这句话对不对?


按照目前的情况来看,JS 自从支持了 Web Worker 之后,就不再是单线程语言了,但 Worker 的工作线程与主线程有区别,在 Worker 的工作线程中无法直接操作 DOM、window 对象或大多数浏览器 API(如 localStorage),Worker 的全局对象也不再是 window 对象,而是 self。


Worker 中的事件循环与主线程相互独立,互不影响,但执行顺序还是得遵循 JS 的语法规则。


宏任务


宏任务表示执行时间较长的任务,在每次时间循环时只会执行一个宏任务,执行完毕后处理微任务队列,所有微任务都执行完毕后进入下一个宏任务。


JS 常见宏任务类型:

  1. 定时器任务:setTimeout / setInterval

  2. DOM 事件回调(如 click、scroll)

  3. I/O 操作(如文件读取、网络请求)

  4. 浏览器用于执行动画的方法 requestAnimationFrame ,执行时机与渲染相关

  5. Node.js 环境的 setImmediate

  6. script 标签内主线程的同步代码(整体作为一个宏任务)


微任务


微任务表示更轻量的异步任务,当宏任务执行完毕之后立即执行。


JS 常见微任务类型:

  1. Promise.then() / Promise.catch() / Promise.finally()

  2. 浏览器监听 DOM 变化的 API 对象,比如:MutationObserver

  3. 手动添加微任务 API 方法:queueMicrotask()

  4. nodejs 中的 process.nextTick()


代码解析


看这么一段代码:


(function() {  console.log(1)  setTimeout(() => { console.log(2); });  queueMicrotask(() => console.log(3))  new Promise(resolve => {    console.log(4);    setTimeout(() => {      resolve();      console.log(5);    }, 0);    Promise.resolve().then(() => console.log(6));    console.log(7);  }).then(() => {    console.log(8);    Promise.resolve().then(() => console.log(9));  });  console.log(10);})();
复制代码


分析代码:


(function() {  console.log(1) // 同步任务  setTimeout(() => { console.log(2); });  queueMicrotask(() => console.log(3))  new Promise(resolve => {    console.log(4); // 同步任务    setTimeout(() => { // 宏任务      resolve(); // 宏任务的同步任务      console.log(5); // 宏任务中的同步任务    }, 0);    Promise.resolve().then(() => console.log(6)); // 微任务    console.log(7); // 同步任务  }).then(() => { // 微任务    console.log(8); // 微任务中的同步任务    Promise.resolve().then(() => console.log(9)); // 微任务中的微任务  });  console.log(10); // 同步任务})();
复制代码


第一轮


首先同步代码的宏任务优先级最高,不管微任务还是宏任务,同步代码都会先执行。


所以上面代码会优先执行:

console.log(1)console.log(4);console.log(7);console.log(10);
复制代码


接着开始处理微任务:

queueMicrotask(() => console.log(3))Promise.resolve().then(() => console.log(6));
复制代码


微任务处理完,开始执行下一轮宏任务。


第二轮

这一轮中的宏任务只有一个 setTimeout,执行完之后由于没有微任务队列,所以直接执行下一轮宏任务。

setTimeout(() => { console.log(2); });
复制代码


第三轮

这一轮的宏任务中有同步代码。

setTimeout(() => { // 宏任务  resolve(); // 宏任务的同步任务  console.log(5); // 宏任务中的同步任务}, 0);
复制代码


在执行完 resolve() 之后,会将 Promise.then 的回调函数放入微任务队列中,所以在宏任务执行完之后会开始微任务:

then(() => { // 微任务  console.log(8); // 微任务中的同步任务  Promise.resolve().then(() => console.log(9)); // 微任务中的微任务})
复制代码


最终的打印顺序

14710362589
复制代码


执行流程图


JS 代码逐行执行,在遇到宏任务时,整个代码块丢到宏任务队列,在遇到微任务时,将微任务丢到本次事件循环中的微任务队列,本次事件循环执行完之后,再执行微任务队列中的任务,微任务执行完之后开始下一个宏任务执行。


JS 代码执行机制:



宏任务执行机制:



写在最后


JS 中的代码执行流程永远都是事件循环机制,这是 JS 的任务调度核心,理解事件循环机制,才能在开发中游刃有余~~


文章转载自:前端路引

原文链接:https://www.cnblogs.com/linx/p/18943769

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
Web前端入门:JavaScript 事件循环机制中的微任务与宏任务_JavaScript_量贩潮汐·WholesaleTide_InfoQ写作社区