Skip to content

事件循环

JavaScript 的事件循环(Event Loop)是其异步编程模型的核心机制,它使得 JavaScript 能够在单线程上执行代码的同时处理异步操作(如网络请求、定时器等)。理解事件循环对于编写高效且无阻塞的 JavaScript 代码至关重要。以下是关于 JavaScript 事件循环的基本概念和工作流程的概述:

基本概念

  1. 调用栈(Call Stack):这是 JavaScript 执行函数的地方。每当一个函数被调用时,它就会被添加到调用栈中,并在执行完成后从栈中移除。

  2. 任务队列(Task Queue):分为宏任务(macrotask)和微任务(microtask)两种类型。宏任务包括整体代码块、setTimeoutsetInterval、I/O、UI 渲染等;微任务包括Promise的回调、MutationObserver等。

  3. 事件循环:负责监控调用栈和任务队列,当调用栈为空时,事件循环会从任务队列中取出任务并推入调用栈中执行。

工作流程

  1. 首先,JavaScript 引擎开始执行全局脚本,所有同步代码都会依次进入调用栈中执行。

  2. 当遇到异步操作(比如定时器或网络请求),这些操作不会直接阻塞执行流,而是被安排在后台运行,完成后将相应的回调函数放入任务队列中。

  3. 在每个任务(无论是宏任务还是微任务)完成后,如果存在微任务,则会立即执行所有的微任务,直到微任务队列为空。

  4. 完成当前宏任务及其所有微任务后,浏览器可以进行必要的渲染操作(这并非总是发生,取决于具体的实现)。

  5. 然后,事件循环继续处理下一个宏任务,重复上述过程。

微任务 vs 宏任务

  • 微任务(Microtasks):优先级较高,在当前任务完成后立即执行,通常用于需要尽快执行的操作,如Promise的回调。
  • 宏任务(Macrotasks):包括但不限于整体代码块、setTimeoutsetInterval等,它们按顺序执行,每次只取一个宏任务来执行。

了解事件循环的工作原理有助于更好地理解 JavaScript 如何管理异步操作以及如何避免常见的陷阱,例如错误地处理异步代码导致的竞态条件或未预期的行为。通过合理使用Promiseasync/await等特性,可以写出更加清晰和高效的异步代码。

Released under the MIT License.