全部学科
Python全栈
python
NodeJS全栈
nodejs
📅 2026-07-03 7 分钟 ✍️ juanwangdev

事件循环与任务队列

JavaScript 单线程通过事件循环实现异步非阻塞,理解其调度机制是写出正确异步代码的关键。

事件循环机制

核心组件

JavaScript
调用栈 → 执行同步代码
  ↓ 遇到异步操作
Web APIs → 定时器/网络请求等(浏览器提供)
  ↓ 完成后
任务队列 → 等待回调入栈
  ↓ 调用栈空闲
事件循环 → 将回调推入调用栈

执行流程

JavaScript
console.log('1');

setTimeout(() => {
  console.log('2');
}, 0);

console.log('3');

// 输出: 1 → 3 → 2

执行过程:

  1. 同步代码 console.log('1') 入栈执行
  2. setTimeout 交给 Web API 定时,回调放入宏任务队列
  3. console.log('3') 入栈执行
  4. 调用栈清空后,事件循环从宏任务队列取出回调执行

宏任务与微任务

宏任务 (MacroTask)

来源示例
setTimeoutsetTimeout(fn, 0)
setIntervalsetInterval(fn, 1000)
I/O文件读取、网络请求
UI 渲染浏览器渲染帧

微任务 (MicroTask)

来源示例
Promise.then/catch/finallyPromise.resolve().then(fn)
MutationObserverDOM 变化监听
queueMicrotaskqueueMicrotask(fn)

执行优先级

JavaScript
同步代码 > 微任务 > 宏任务

每个宏任务执行完后,会清空微任务队列:

text
console.log('1');

setTimeout(() => {
  console.log('2');
  Promise.resolve().then(() => console.log('3'));
}, 0);

Promise.resolve().then(() => {
  console.log('4');
  setTimeout(() => console.log('5'), 0);
});

console.log('6');

// 输出: 1 → 6 → 4 → 2 → 3 → 5
步骤操作输出
1同步代码1, 6
2清空微任务队列4
3取宏任务22
4清空微任务(3入队)3
5取宏任务55

嵌套示例

text
setTimeout(() => {
  console.log('宏任务1');
  Promise.resolve().then(() => {
    console.log('微任务1');
  });
}, 0);

setTimeout(() => {
  console.log('宏任务2');
}, 0);

Promise.resolve().then(() => {
  console.log('微任务2');
  setTimeout(() => {
    console.log('宏任务3');
  }, 0);
});

console.log('开始');

// 输出: 开始 → 微任务2 → 宏任务1 → 微任务1 → 宏任务2 → 宏任务3

要点总结

  1. 同步代码先执行完,再处理异步队列
  2. 微任务优先级高于宏任务,每个宏任务后清空微任务队列
  3. Promise.then 是微任务,setTimeout 是宏任务
  4. 微任务队列不清空,渲染不会进行
  5. 理解事件循环有助于调试异步执行顺序问题
想在手机上练习这篇文章的配套题目?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一篇 数组基础与操作
下一篇 → 异步编程核心概念
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码