资讯详情

JavaScript 的事件循环——宏任务与微任务到底谁先执行

📅 2026/10/21 2:35:45 | 华诺云谱 👁 阅读
JavaScript 的事件循环——宏任务与微任务到底谁先执行
JS 是单线程的却能同时处理定时器、网络请求、用户交互。这背后靠的是事件循环。但很多人学到事件循环时会被宏任务微任务这两个词卡住它们是什么为什么有时候先执行后面的代码再回头执行前面的回调这篇文章只讲这一个问题把事件循环和任务队列讲透。一、单线程与任务队列JS 在主线程上执行代码同一时刻只能做一件事。这是为了避免多线程同时操作页面导致混乱。但单线程有个问题遇到耗时操作怎么办如果傻等页面就卡死了。所以 JS 把耗时操作交给浏览器或底层去处理主线程继续往下走。等底层处理完了把回调放进一个队列里排队。主线程手头的同步代码执行完后就去队列里取回调来执行。取一个执行一个执行完再取下一个。这个不断循环的过程就是事件循环。二、宏任务与微任务的区分队列里的任务并不是一视同仁的。它们被分成两类宏任务和微任务。宏任务包括整体代码脚本、定时器回调、事件回调、网络请求完成后的回调等。可以理解为比较大块的工作。微任务包括Promise 的成功和失败回调、某些观察者回调等。可以理解为当前工作完成后需要立刻处理的小事。关键区别在于执行时机。每执行完一个宏任务引擎会把当前产生的所有微任务全部执行完然后才去取下一个宏任务。微任务的优先级高于宏任务。三、执行顺序的完整规则一次完整的事件循环大致是这样的执行当前宏任务中的同步代码。同步代码执行完检查微任务队列。把微任务队列里的任务全部执行完一个不剩。微任务清空后如果有必要进行页面渲染。取下一个宏任务重复上述过程。这个规则解释了很多反直觉的输出顺序。比如一段代码里先写了定时器后写了 Promise 回调。直觉上定时器先注册应该先执行但实际上 Promise 回调是微任务会在当前宏任务结束后立刻执行而定时器是宏任务要等下一轮。所以 Promise 回调反而先输出。四、为什么要有微任务微任务的设计是为了处理当前操作完成后必须马上做的事。比如Promise 的状态变化后依赖它的后续逻辑应该尽快执行而不是等到下一轮事件循环。如果放在宏任务里可能会被其他宏任务插队导致状态不同步。微任务保证在当前宏任务结束、页面渲染之前把所有相关的后续处理都做完。这样数据一致渲染结果也正确。但微任务也不能滥用。如果微任务里不断产生新的微任务就会一直执行下去永远轮不到下一个宏任务页面会卡死。所以微任务队列必须能被清空。五、常见误区误区一以为定时器的时间是精确的。定时器只保证不早于设定时间执行。如果主线程忙或者前面有微任务没清完实际执行时间会推迟。误区二以为 Promise 内部代码是异步的。Promise 内部的执行逻辑是同步的只有它的回调是异步的。所以创建 Promise 时里面的代码立刻执行但 then 里的回调要等当前同步代码跑完。误区三以为所有回调都是宏任务。事件回调、定时器回调是宏任务但 Promise 回调是微任务。混淆两者就会算错执行顺序。误区四在微任务里做重活。微任务会阻塞渲染如果在里面做大量计算页面会卡。重活应该放到宏任务或后台线程。六、实际开发中的意义理解事件循环不只是为了应对面试题它对实际开发有直接帮助。排查执行顺序问题。当代码结果和预期不符时能判断是宏任务微任务的顺序导致的而不是逻辑写错了。优化渲染时机。知道微任务在渲染之前执行就能把需要影响渲染的逻辑放在合适的位置避免页面闪烁。避免卡顿。知道微任务会阻塞渲染就不会在微任务里做耗时操作而是拆分到多个宏任务里。理解框架行为。很多前端框架的更新机制建立在微任务之上理解事件循环才能看懂它们为什么这样设计。七、总结事件循环是 JS 单线程处理异步的核心机制。宏任务是较大块的工作微任务是当前工作完成后立刻要处理的小事。每轮循环先执行一个宏任务再清空所有微任务然后才进入下一轮。掌握这套规则你就能准确预测代码执行顺序也能在性能问题出现时知道该往哪里调。这是 JS 异步编程的底层逻辑。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑