返回

JavaScript 事件循环:揭开单线程世界的秘密

前端

JavaScript 原理——事件循环(Event Loop)

引子:单线程的 JavaScript

JavaScript 是单线程语言,这意味着所有任务必须排队执行。前一个任务未完成,后一个任务就不得不等待。如果前一个任务耗时较长,后续任务就会被无限期地阻塞。

任务的分类

为了解决单线程带来的问题,JavaScript 将任务划分为两类:

  • 同步任务: 立即执行,不会将控制权让出。
  • 异步任务: 非立即执行,在某些事件发生后执行。

事件循环

事件循环是一个不断循环的过程,管理 JavaScript 中任务的执行。其工作原理如下:

  • 执行栈: 存储正在执行的同步任务。
  • 事件队列: 存储等待执行的异步任务。
  • 执行流程:
    • 执行栈非空时,执行栈中的任务。
    • 执行栈为空时,从事件队列中取出一个任务放入执行栈执行。
    • 执行栈中的任务结束后,继续从事件队列中取出任务执行。

常见的异步任务

  • 回调函数: 在事件发生后调用的函数。
  • Promise: 用于处理异步操作的语法糖。
  • Web API: 浏览器提供的接口,如 setTimeout、XMLHttpRequest。

浏览器渲染与事件循环

浏览器渲染引擎负责将 HTML、CSS 和 JavaScript 代码转换为用户界面。它会不断检查执行栈和事件队列,并在执行栈为空时执行渲染任务。

异步编程技巧

掌握 JavaScript 的异步编程技巧至关重要:

  • 避免阻塞主线程: 将耗时的任务放入异步队列中。
  • 利用 Promise: 处理异步操作的最佳实践。
  • 异步循环: 使用 setTimeout 或 setInterval 定期执行任务。

示例代码

// 同步任务
console.log("同步任务 1");

// 异步任务
setTimeout(() => {
  console.log("异步任务 1");
}, 0);

// 同步任务
console.log("同步任务 2");

执行顺序:

  1. 同步任务 1
  2. 同步任务 2
  3. 异步任务 1

总结

JavaScript 的事件循环是一个复杂的机制,但掌握其工作原理对于编写高效的异步代码至关重要。通过区分同步和异步任务,了解事件队列和执行栈,以及利用异步编程技巧,您可以避免阻塞主线程,并充分发挥 JavaScript 的非阻塞特性。