javascript事件循环是宿主环境实现的调度机制,非ecmascript规范;其核心为调用栈清空后,依次执行一个宏任务、全部微任务、渲染阶段,循环往复。

JavaScript 事件循环不是“一个队列加一个循环”的简化模型,而是一套由调用栈、两类任务队列、渲染阶段和宿主环境协同驱动的运行时调度机制。它不属 ECMAScript 规范,而是浏览器或 Node.js 这类宿主环境实现的底层协调系统。
调用栈是事件循环的起点和标尺
所有同步代码都在调用栈中线性执行,后进先出。函数入栈即开始执行,出栈即彻底结束。事件循环本身从不干预栈内运行——它只在调用栈完全清空后才启动下一轮调度。这意味着:哪怕 setTimeout(0) 已就绪,只要栈里还有函数没执行完,它的回调就只能等待;微任务也无法打断正在运行的同步逻辑。
宏任务与微任务不是“快慢之分”,而是调度优先级的硬规则
宏任务(如 script 全局代码、setTimeout、setInterval、I/O、UI 渲染)每次仅执行一个;微任务(如 Promise.then/catch/finally、queueMicrotask、MutationObserver)则在**每个宏任务结束后、下一个宏任务开始前**被全部清空。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- Promise 构造函数体是同步执行的,只有 then/catch 回调才是微任务
- async/await 是语法糖,await 后的代码会被编译为 Promise 链的微任务
- 连续触发大量 Promise.then 可能导致微任务堆积,阻塞渲染,造成界面卡顿
渲染不是可选环节,而是事件循环的正式阶段
在浏览器中,事件循环每轮迭代包含明确的“渲染阶段”:微任务队列清空后,若页面状态有变更(如 DOM 修改、CSS 更新),浏览器会主动触发一次样式计算、布局、绘制流程。这个阶段不可跳过,也不能被 JS 代码直接控制。requestAnimationFrame 的回调就插入在此阶段之前,用于精准对齐下一帧。
- 频繁修改 DOM + 紧跟读取 offsetHeight 等布局属性,会强制触发重排,拖慢循环节奏
- 把耗时操作拆成微任务(如 queueMicrotask)并不能加速渲染,反而可能延迟它
宿主差异决定行为边界
事件循环是宿主提供的机制,不同环境实现不同:
- 浏览器按清晰阶段划分:宏任务 → 微任务 → 渲染 → 下一宏任务
- Node.js 分为 timers、pending callbacks、poll、check、close callbacks 五个阶段,setImmediate() 和 setTimeout(fn, 0) 执行时机可能反转
- Web Worker 拥有独立的事件循环,与主线程内存隔离,但内部调度逻辑一致
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










