在 JavaScript 的世界里,异步编程是灵魂。从早期的“回调地狱”到现在的 async/awaitPromise 始终是承上启下的核心。

无论你是刚入行的新手,还是准备面试的开发者,这篇全方位的 Promise 总结都值得你收藏。

一、 基础知识:Promise 到底是什么? 1. 三种状态

Promise 就像一份“未来的承诺”,它必然处于以下三种状态之一:

  • Pending(待定) :初始状态,既没有被兑现,也没有被拒绝。

  • Fulfilled(已兑现/成功) :操作成功完成。

  • Rejected(已拒绝/失败) :操作失败。

核心特性:状态一旦改变(从 Pending 变为 Fulfilled 或 Rejected),就不可逆转,且无法再次更改。
2. 执行顺序(微任务)

Promise 的回调属于微任务(Microtask)。在事件循环中,微任务的优先级高于 setTimeout 等宏任务。

二、 核心 API 全解析

掌握这些标准方法,能解决 90% 的异步场景。

1. 实例方法

  • ** .then() **:接收成功的结果。

  • ** .catch() **:捕获错误。

  • ** .finally() **:无论成功失败都会执行(常用于关闭 Loading 动画)。

2. 静态方法(并发控制)

方法

特点

适用场景

Promise.all([p1, p2])

全部成功才成功, 一个失败则全部失败

多个关联请求同时发送,缺一不可。

Promise.allSettled() 等待所有结果

,无论成功或失败。

批量任务处理,需知道每个任务的具体状态。

Promise.race() 谁快谁赢

,只取第一个完成的结果(不论成败)。

接口超时处理。

Promise.any()

只要有一个成功就成功;全部失败才失败。

多源镜像加速,取最快响应的可用资源。

三、 那些年我们踩过的 Promise 坑 1. 幽灵般的“静默失败”

现象:忘记写 .catch(),导致程序运行异常却没有任何日志。对策:全局监听 unhandledrejection 事件作为兜底,并在代码中养成随手 catch 的习惯。

2. 嵌套地狱的“变种”

虽然有了 Promise,但很多人还是写出了嵌套结构:

// ❌ 错误:Promise 套娃
getData().then(res => {
getOtherData(res).then(secondRes => {
// ...这和回调地狱没区别
})
})

// ✅ 正确:链式调用
getData()
.then(res => getOtherData(res))
.then(secondRes => updateView(secondRes))

3. 消失的返回值

.then() 内部如果没有 return,下一个链条接收到的值就是 undefined。这是导致业务逻辑断裂的最常见原因。

四、 TypeScript 中的进阶实践

在 TS 环境下,Promise 需要更严谨的对待:

1. 拒绝 Promise

明确定义返回类型。

interface User { id: number; name: string; }

// ✅ 明确标注返回类型,享受类型推导
async function getUser(id: number): Promise {
const res = await fetch(`/api/user/${id}`);
return res.json();
}

2. 异步循环的误区

forEach 中写 await 是无效的。

  • 错误list.forEach(async item => { await doSomething() }) —— 循环会瞬间结束。

  • 正确 :使用 for...of (串行)或 Promise.all(list.map(...)) (并行)。

五、 大厂避坑经验总结
  1. 始终返回 Promise :让你的函数具备“可组合性”。

  2. Await 嵌套优化 :如果两个异步操作没有依赖关系,不要串行 await ,请使用 Promise.all 提速。

// ❌ 慢了一倍
const a = await getA();
const b = await getB();

// ✅ 并行执行
const [a, b] = await Promise.all([getA(), getB()]);

  1. 异常捕获策略 :在异步函数中,优先使用 try...catch 配合 async/await ,它能让异步代码读起来像同步代码一样清晰。

结语

Promise 是异步编程的基石。理解它的状态流转、掌握并发控制 API、并在 TS 中保持类型严谨,能让你避开 99% 的生产环境 Bug。

避坑金句:

“如果一个函数返回 Promise,那么调用它时,要么 await 它,要么 return 它,要么 catch 它。”