JavaScript的Event Loop (超详细)

139 阅读2分钟

JavaScript的事件循环(Event Loop)是JavaScript运行时的核心概念之一,尤其对于理解异步编程非常重要。由于JavaScript是单线程的,这意味着它一次只能执行一个任务。为了有效地管理多个任务,JavaScript使用事件循环来调度任务。

JavaScript事件循环的基本组成部分:

  1. 执行上下文栈 (Execution Context Stack):存储当前执行的函数上下文。
  2. 调用队列 (Call Queue) 或 任务队列 (Task Queue):存放等待执行的任务。
  3. Web APIs:例如setTimeoutXMLHttpRequestfetch等,它们可以触发异步事件。
  4. 消息队列 (Message Queue):存放异步回调函数。
  5. 微任务队列 (Microtask Queue):存放需要立即执行的任务,如Promise.then回调。

事件循环的工作流程:

  1. 同步任务:当JavaScript引擎开始执行脚本时,所有的同步任务都会按顺序执行。
  2. 异步任务:当遇到异步任务时(如setTimeoutfetch请求等),这些任务会被委托给Web API去处理,并且不会阻塞主线程。
  3. 回调注册:异步任务完成后,其回调函数会被放入消息队列中。
  4. 检查队列:当执行栈为空时,事件循环会检查消息队列是否有待处理的任务。
  5. 执行任务:如果消息队列中有任务,则将队列中的第一个任务取出并放入执行栈中执行。
  6. 重复步骤4和5:直到消息队列为空。

微任务与宏任务

  • 宏任务 (Macro Task): 包括整体的script执行、setTimeoutsetInterval等。
  • 微任务 (Micro Task): 主要在每个宏任务执行完毕之后立即执行,如PromiseMutationObserver等。

示例

假设以下JavaScript代码:

输出顺序将是:

  1. start
  2. end
  3. Promise
  4. setTimeout

这是因为Promise.then回调属于微任务,而setTimeout属于宏任务。当同步任务执行完毕后,微任务队列中的任务会立即执行,然后才是宏任务队列中的任务。

以上就是JavaScript事件循环的基本概念及其工作原理。理解这些概念对于编写高效的异步JavaScript代码至关重要。