跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
JavaScript事件循环
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:JavaScript事件循环}} '''JavaScript事件循环'''(Event Loop)是JavaScript运行时处理异步操作的核心机制,它决定了代码的执行顺序,尤其是在单线程环境下实现非阻塞I/O操作的关键。本文将深入解析事件循环的工作原理、组成部分及实际应用。 == 概述 == JavaScript是单线程语言,但通过'''事件循环'''机制实现了异步编程能力。事件循环负责协调调用栈(Call Stack)、消息队列(Message Queue)和微任务队列(Microtask Queue)的工作,确保非阻塞执行。 === 核心组件 === * '''调用栈(Call Stack)''':记录函数调用的栈结构,后进先出(LIFO)。 * '''Web APIs''':浏览器提供的异步功能(如`setTimeout`、`fetch`)。 * '''任务队列(Task Queue)''':存放宏任务(如`setTimeout`回调)。 * '''微任务队列(Microtask Queue)''':存放微任务(如`Promise.then`回调)。 == 工作原理 == 事件循环的流程如下: 1. 执行调用栈中的同步代码。 2. 遇到异步操作时,交给Web API处理,完成后将回调放入对应队列。 3. 当调用栈为空时,优先清空微任务队列,再处理一个宏任务,循环往复。 <mermaid> graph LR A[调用栈] -->|同步代码| B[执行完毕] B -->|异步操作| C[Web APIs] C -->|宏任务回调| D[任务队列] C -->|微任务回调| E[微任务队列] D -->|调用栈空| F[事件循环] E -->|优先处理| F F --> A </mermaid> === 代码示例 === 以下示例展示事件循环的执行顺序: <syntaxhighlight lang="javascript"> console.log('Start'); setTimeout(() => console.log('Timeout'), 0); Promise.resolve().then(() => console.log('Promise')); console.log('End'); </syntaxhighlight> '''输出:''' <pre> Start End Promise Timeout </pre> '''解释:''' 1. 同步代码`console.log('Start')`和`console.log('End')`首先执行。 2. `Promise.then`微任务优先于`setTimeout`宏任务执行。 == 宏任务与微任务 == * '''宏任务''':`setTimeout`、`setInterval`、I/O操作。 * '''微任务''':`Promise.then`、`MutationObserver`、`queueMicrotask`。 === 执行优先级 === 微任务队列会在当前宏任务结束后立即清空,而宏任务需等待下一次事件循环。 <syntaxhighlight lang="javascript"> console.log('宏任务1'); setTimeout(() => console.log('宏任务2'), 0); Promise.resolve().then(() => { console.log('微任务1'); queueMicrotask(() => console.log('微任务2')); }); console.log('宏任务1结束'); </syntaxhighlight> '''输出:''' <pre> 宏任务1 宏任务1结束 微任务1 微任务2 宏任务2 </pre> == 实际应用场景 == === 用户交互优化 === 通过将耗时操作放入微任务队列,避免阻塞UI渲染: <syntaxhighlight lang="javascript"> button.addEventListener('click', () => { // 宏任务:触发重绘 setTimeout(() => updateUI(), 0); // 微任务:处理数据 Promise.resolve().then(() => processData()); }); </syntaxhighlight> === 性能监控 === 利用事件循环测量代码执行时间: <syntaxhighlight lang="javascript"> function measure() { const start = performance.now(); queueMicrotask(() => { console.log(`耗时:${performance.now() - start}ms`); }); } </syntaxhighlight> == 数学表示 == 事件循环的调度过程可用以下公式描述: <math> \text{EventLoop} = \bigcup_{i=1}^{n} \left( \text{MacroTask}_i + \text{MicroTasks}^* \right) </math> 其中<math>\text{MicroTasks}^*</math>表示当前所有微任务。 == 常见误区 == * '''误区1''':`setTimeout(fn, 0)`会立即执行。<br> '''纠正''':实际是放入宏任务队列,等待调用栈清空。 * '''误区2''':微任务会中断当前宏任务。<br> '''纠正''':微任务仅在当前宏任务'''结束后'''执行。 == 总结 == JavaScript事件循环通过协调调用栈、任务队列和微任务队列,实现了单线程下的高效异步处理。理解其优先级规则(微任务 > 宏任务)对编写高性能代码至关重要。 [[Category:编程语言]] [[Category:JavaScript]] [[Category:Javascript异步编程]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)