前端事件循环

前端事件循环(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

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

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

执行优先级

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

微任务的嵌套执行

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

相关推荐
里欧跑得慢11 小时前
17. Flutter Hero动画实现:让界面过渡更加优雅
前端·css·flutter·web
IT_陈寒12 小时前
Vue的这个响应式陷阱,我debug了一整天才爬出来
前端·人工智能·后端
cn_mengbei12 小时前
用React Native开发OpenHarmony应用:Reanimated共享元素过渡
javascript·react native·react.js
kyriewen12 小时前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
去伪存真12 小时前
我自己写的第一个skills--project-core-standards
前端·agent
Data_Journal12 小时前
如何使用cURL更改User Agent
大数据·服务器·前端·javascript·数据库
掌心向暖RPA自动化13 小时前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
竹林81813 小时前
wagmi v2 多链钱包切换:一个 Uniswap 仿盘项目让我踩了三天坑
前端·javascript
donecoding13 小时前
Playwright MCP 页面捕获:Snapshot、截图、HTML 到底选哪个?
前端·ai编程·前端工程化
你也向往长安城吗13 小时前
最快的 JavaScript navmesh pathfinding3d 算法。
javascript