JavaScript 异步与 Promise 笔记
1. JavaScript 异步机制概览
1.1 执行栈与事件循环
- JS 是单线程执行
- 执行栈(Call Stack):存储同步任务
- 任务队列(Task Queue / Microtask Queue):
- 宏任务(Macro Task):setTimeout、setInterval、I/O、UI 渲染
- 微任务(Micro Task):Promise.then/catch/finally、MutationObserver
- 事件循环(Event Loop):
- 执行同步任务直到栈空
- 执行微任务队列
- 执行宏任务队列
- 重复循环
1.2 异步类型示意
| 类型 | 示例 | 队列类型 |
|---|---|---|
| 微任务 | Promise.then, MutationObserver | Microtask |
| 宏任务 | setTimeout, setInterval, I/O | Macrotask |
1 | console.log('script start'); |
2. Promise 基础与用法
2.1 创建 Promise
1 | const promise = new Promise((resolve, reject) => { |
2.2 Promise 状态
- Pending:初始状态
- Fulfilled:成功
- Rejected:失败
状态只能从 Pending 变为 Fulfilled 或 Rejected,且不可逆
2.3 Promise 用法
1 | promise |
2.4 Promise 链式调用
1 | Promise.resolve(1) |
2.5 Promise.all / allSettled / race / any
1 | const p1 = Promise.resolve(1); |
3. async / await 高阶用法
3.1 基本语法
1 | async function fetchData() { |
3.2 错误处理
1 | async function test() { |
3.3 并发与串行
- 串行(等待前一个完成再执行下一个)
1 | const result1 = await asyncFunc1(); |
- 并发(同时发起请求,等待全部完成)
1 | const [result1, result2] = await Promise.all([asyncFunc1(), asyncFunc2()]); |
4. 底层原理与微任务机制
4.1 Promise.then 微任务原理
- then/catch/finally 会在微任务队列中注册回调
- 微任务优先于宏任务执行
1 | console.log(1); |
4.2 Promise 内部执行流程
- 创建 Promise,状态 Pending
- then 注册回调函数到微任务队列
- resolve/reject 改变状态,异步执行注册回调
4.3 async/await 本质
- async 函数返回 Promise
- await 后面跟 Promise,本质是
Promise.then(...) - 可以理解为语法糖,更直观处理异步逻辑
5. 常见异步陷阱
- 忘记 return promise 链
1 | // ❌ |
- 在 forEach 中使用 await
1 | arr.forEach(async item => { |
- 推荐使用
for...of或map + Promise.all
- Promise 内抛异常未捕获
1 | new Promise((resolve, reject) => { throw new Error('err'); }) |
6. 高级优化策略
- 批量异步请求
1 | const results = await Promise.all(requests.map(req => fetch(req))); |
- 并发限制
1 | async function limitConcurrent(tasks, limit) { |
- 取消异步请求
- 使用
AbortController或第三方库(axios cancel token)
7. 面试要点
- 异步队列与事件循环原理
- Promise 状态与链式调用
- async/await 与 Promise 的关系
- 微任务与宏任务区别
- 并发控制与错误处理
- 常见坑:forEach + await、未 return Promise、异常未捕获