前端事件循环

前端事件循环(Event Loop)是 JavaScript 运行时处理异步任务的核心机制,它决定了代码执行的顺序和优先级,使 JavaScript 在单线程环境中高效处理异步任务,确保用户界面的流畅性和响应性。

单线程与异步执行的矛盾

JavaScript 在浏览器环境中是单线程运行的,这意味着它同一时间只能执行一个任务。例如,当执行一段复杂的计算任务时,其他任务(如用户点击事件、页面渲染)都必须等待该计算完成。这种特性在处理需要大量时间的任务时,可能会导致页面卡顿,影响用户体验。然而,前端开发中存在许多耗时操作,如网络请求(fetch)、定时器(setTimeoutsetInterval)等。如果这些操作都以同步方式执行,整个页面将会冻结,直到操作完成。为了解决这个矛盾,JavaScript 引入了事件循环机制,它允许在执行同步任务的同时,异步处理其他任务。

工作原理

调用栈

同步代码逐行执行(后进先出,LIFO)

函数调用时入栈,执行完毕出栈

任务队列

宏任务队列(MacroTask Queue)setTimeoutsetInterval、DOM 事件回调、I/O 操作

微任务队列(MicroTask Queue)Promise.thenMutationObserverqueueMicrotask

渲染管线(Render Pipeline) :样式计算、布局、绘制(requestAnimationFrame 回调在此阶段执行)

事件循环流程

markdown 复制代码
while (true) {
  1. 执行调用栈中的同步代码(直到栈空)
  2. 执行所有微任务(清空微任务队列)
  3. 渲染页面(如果需要)
  4. 取一个宏任务执行
}

事件循环不断检查调用栈是否为空。当调用栈为空时,事件循环从任务队列中取出一个任务(回调函数),将其压入调用栈执行。如此循环往复,实现异步任务的有序执行。

示例

javascript 复制代码
console.log('1'); // 同步代码

setTimeout(() => {
  console.log('2'); // 宏任务
  Promise.resolve().then(() => console.log('3')); // 微任务
}, 0);

Promise.resolve().then(() => {
  console.log('4'); // 微任务
  setTimeout(() => console.log('5'), 0); // 宏任务
});

// 输出顺序:1 → 4 → 2 → 3 → 5

事件循环每次从宏任务队列中取出一个宏任务执行。在执行宏任务过程中,可能会产生新的宏任务或微任务。

在当前宏任务执行完毕后,事件循环会立即处理微任务队列中的所有微任务,直到微任务队列为空,才会去取下一个宏任务。

执行优先级

同步代码 > 微任务 > 宏任务 > 渲染

微任务的嵌套执行

微任务队列必须完全清空后,才会执行下一个宏任务或渲染

相关推荐
程序员黑豆9 小时前
Java 注释详解:单行、多行与文档注释的完整指南
java·前端·ai编程
剪刀石头布啊9 小时前
antd中可编辑表格中巧用useWatch实现联动高性能效果,以及定制延伸学习
前端
油丶酸萝卜别吃9 小时前
前端转全栈学习路线
前端·学习
浮生望10 小时前
前端路由进阶:History API原理与手写HistoryRouter
前端
陆枫Larry10 小时前
JavaScript 中的竞态是什么,为啥会有竟态?
前端
上海安当技术12 小时前
半天接入:USBKey RESTful API + C 动态库,Web 和 C/S 两套集成路径实战
前端·后端·restful·集成·usbkey
DevUI团队12 小时前
从“即兴创作”到“规格先行”,华为云码道(CodeArts)代码智能体持续深耕企业级规范驱动开发能力
前端·人工智能·后端
weixin_4316004413 小时前
NestJS 入门(3):Guard 如何挡住未登录请求?
前端·后端·学习·nest.js
avi911114 小时前
[AI教做人]AI平台做2项目;一个3D模型展示,另一个框架多人
javascript·人工智能·ai·3d模型·3d引擎·顶点和法线
kyriewen14 小时前
我用Claude Code两天干完了团队两周的排期——周报发出去那一刻我就后悔了
前端·javascript·ai编程