Skip to content

JavaScript 事件循环

约 605 字大约 2 分钟

JavaScript

2024-06-13

JavaScript 事件循环(Event Loop)不会在没有任务时主动检查队列,而是进入“空闲状态”**,等待新的任务触发。


1. 事件循环机制

JavaScript 的事件循环由两大任务队列组成:

  • 微任务队列(Microtask Queue):包括 Promise.then()MutationObserverqueueMicrotask() 等。
  • 宏任务队列(Macrotask Queue):包括 setTimeout()setInterval()setImmediate()MessageChannel、I/O 事件等。

事件循环的步骤如下:

  1. 执行同步代码(脚本整体代码)
  2. 执行微任务队列(一次性清空所有微任务)。
  3. 执行下一个宏任务(如果有的话)
  4. 重复步骤 2 & 3,直到所有任务处理完
  5. 如果微任务 & 宏任务都为空,JS 线程进入“空闲状态”,等待新的任务到来

2. JS 线程在任务队列为空时的行为

当前线程没有微任务、没有宏任务 时,JS 线程会 停止执行,不会主动轮询检查任务队列,而是 等待新的事件触发

  • 如果没有新任务,JS 线程进入休眠(Idle 状态),不会浪费 CPU 资源。
  • 一旦有新的任务(比如用户交互、网络请求返回、定时器触发),事件循环会重新启动,执行新的任务。

🚀 示例:所有任务都执行完毕,JS 线程进入空闲

console.log("同步代码");

// 添加微任务
Promise.resolve().then(() => console.log("微任务 1"));

// 添加宏任务
setTimeout(() => console.log("宏任务 1"), 0);

console.log("同步代码结束");

执行顺序:

同步代码
同步代码结束
微任务 1  <-- 清空所有微任务
宏任务 1  <-- 执行宏任务
(然后 JS 线程进入空闲状态,等待新的任务)

🛑 这里不会无限循环检查队列,如果没有新的任务,JS 线程就进入休眠。


3. 什么情况下 JS 线程会持续运行?

只有当新的任务不断加入,JS 线程才会继续运行!

情况 1:定时器(宏任务)不断触发

setInterval(() => console.log("定时任务"), 1000);
  • setInterval() 每隔 1 秒加入一个新的宏任务,JS 线程不会进入休眠。

情况 2:递归的 queueMicrotask()Promise.then()(微任务)

function loop() {
  console.log("微任务执行");
  queueMicrotask(loop); // 递归触发微任务
}

loop();
  • 这种情况会阻塞 JS 线程,导致主线程一直繁忙,页面无法响应交互(类似 死循环)。

更新日志

2025/6/15 11:14
查看所有更新日志
  • 13186-initial