JavaScript 事件循环
JavaScript 事件循环(Event Loop)不会在没有任务时主动检查队列,而是进入“空闲状态”**,等待新的任务触发。
1. 事件循环机制
JavaScript 的事件循环由两大任务队列组成:
- 微任务队列(Microtask Queue):包括
Promise.then()
、MutationObserver
、queueMicrotask()
等。 - 宏任务队列(Macrotask Queue):包括
setTimeout()
、setInterval()
、setImmediate()
、MessageChannel
、I/O 事件等。
事件循环的步骤如下:
- 执行同步代码(脚本整体代码)。
- 执行微任务队列(一次性清空所有微任务)。
- 执行下一个宏任务(如果有的话)。
- 重复步骤 2 & 3,直到所有任务处理完。
- 如果微任务 & 宏任务都为空,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于