JavaScript 异步(Promise)
本文全面讲解 Promise:创建、链式调用、组合、错误处理与常见陷阱,是前端异步编程的核心标准。
你是否想过:
如何表示一个暂时还不存在的值?如何告别深层嵌套回调,写出近乎同步写法的异步代码?
// 回调地狱 getUser(userId, function(user) { getPosts(user.id, function(posts) { getComments(posts[0].id, function(comments) { console.log(comments) }) }) }) // Promise 扁平写法 getUser(userId) .then(user => getPosts(user.id)) .then(posts => getComments(posts[0].id)) .then(comments => console.log(comments))Promise是代表异步操作最终完成 / 失败的对象,ES2015(ES6)标准化。你可以把它理解为:餐厅取餐号—— 现在没食物,但承诺做好后给你结果。
本文你将学到
- Promise 是什么、为何诞生
- 三种状态:pending /fulfilled/rejected
- 用构造函数创建 Promise
- 使用
.then()/.catch()/.finally() - Promise 链式调用原理
- 所有静态方法:all /allSettled/race /any/resolve /reject/withResolvers /try
- 常用模式与避坑指南
前置知识:回调函数(Callback)。
一、什么是 Promise?
Promise 是一个代表异步操作最终结果的 JS 对象。它的含义:我现在没有值,但我保证之后给你结果(或错误)。
// 1秒后决议的 Promise const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello from the future!') }, 1000) }) promise.then(value => { console.log(value) // 1秒后输出 })与回调不同:Promise 是返回的对象,而非传入的函数。这让链式调用、组合、统一错误处理成为可能。
二、餐厅取餐类比
- 你下单 → 调用异步函数
- 拿到取餐号 →得到 Promise 对象
- 等待做菜 →pending(进行中)
- 餐做好 →fulfilled(成功)
- 食材用完 →rejected(失败)
- 取餐 →
.then() - 处理问题 →
.catch()
关键特性:一旦落定(settled),状态永久不变。
三、为什么需要 Promise?(回调的问题)
- 嵌套地狱(金字塔代码)
- 错误处理分散、重复
- 无法组合并行 / 串行流程
- 同步 / 异步行为不一致
Promise 提供:
- 扁平链式结构
- 统一错误捕获
- 强大的并发控制
- 确定性异步行为
四、Promise 三态与命运
三种状态(State)
- pending:初始状态,进行中
- fulfilled:成功,有结果值
- rejected:失败,有错误原因
重要规则
- 一旦从 pending → fulfilled /rejected,状态永久锁定
resolve()/reject()多次调用只生效第一次
命运(Fate)
- resolved:命运已锁定(可能仍 pending,但会跟随内部 Promise)
- unresolved:未锁定
五、Thenable 对象
任何拥有.then()方法的对象都叫thenable。JS 会自动把它当作 Promise 兼容处理,实现库间互操作。
const thenable = { then(onFulfilled) { onFulfilled(42) } } Promise.resolve(thenable).then(console.log) // 42六、创建 Promise
1. 构造函数
const p = new Promise((resolve, reject) => { // 同步立即执行 // 成功 → resolve(value) // 失败 → reject(error) })2. 包装回调式 API
function loadImage(url) { return new Promise((resolve, reject) => { const img = new Image() img.onload = () => resolve(img) img.onerror = () => reject(new Error('load failed')) img.src = url }) }3. 快速创建
Promise.resolve(值) Promise.reject(错误)七、消费 Promise:then /catch/finally
1..then()
核心方法,接收成功回调,返回新 Promise。
2..catch()
捕获链中任何错误,等价于.then(undefined, err => {})。
3..finally()
无论成功 / 失败都会执行,用于清理(关闭加载、释放资源)。
八、Promise 链式调用(核心能力)
每一个.then()都返回新 Promise,形成扁平流程。
Promise.resolve(1) .then(x => x + 1) // 2 .then(x => x + 1) // 3 .then(console.log)规则:
- 返回普通值 → 作为下一个 then 的值
- 返回 Promise → 等待它决议再继续
- 抛出错误 → 进入最近 catch
九、错误处理(超级强大)
- 错误会自动穿透整条链,直到被 catch
- 一个 catch 捕获所有上游错误
- 可 catch 后恢复流程
getUser() .then(user => getPosts(user.id)) .then(posts => getComments(posts[0].id)) .catch(err => console.error('任意一步出错:', err))十、Promise 静态方法(必背)
1.Promise.all([])
- 全部成功才成功
- 任意失败立即失败(短路)
- 并行执行,等待全部
2.Promise.allSettled([])
- 永远不失败
- 等待全部落定
- 返回每个结果的状态与值
3.Promise.race([])
- 谁先落定谁赢
- 成功失败都算结束
- 常用于超时控制
4.Promise.any([])
- 谁先成功谁赢
- 忽略失败
- 全部失败才返回 AggregateError
5.Promise.withResolvers()(ES2024)
直接外部获取 resolve/reject,更简洁。
const { promise, resolve, reject } = Promise.withResolvers()6.Promise.try()(Baseline 2025)
统一处理同步 / 异步函数,捕获同步抛出。
十一、常用异步模式
1. 串行执行(依赖前序结果)
for...of + await
2. 并行执行(互不依赖)
Promise.all
3. 分批并行(防限流)
slice + 循环 + Promise.all
4. 重试机制
循环 + catch + delay
5. 回调转 Promise(Promisify)
包装成 (resolve, reject) 形式
十二、常见错误(高频坑)
- 忘记 return→ 链断裂、undefined
- 嵌套而非链式→ 重回回调地狱
- new Promise 包裹已有 Promise(反模式)
- 没有 catch→ 未处理拒绝崩溃 / 警告
- forEach + async→ 不等待,直接继续
- 微任务时序误解:then 永远在同步代码之后
十三、核心要点总结
- Promise = 异步结果占位符
- 三态:pending → fulfilled /rejected
- 一旦落定,不可改变
- then 返回新 Promise → 支持链式
- 错误自动穿透,一个 catch 搞定
- 并行 / 竞速 / 超时 / 重试都靠静态方法
- 是 async/await 的基础
概念 汇总
一、核心基础
- Promise同类:Future、Deferred、异步契约、Task
- 异步占位值同类:延迟计算、未来值
- Promise 状态(pending/fulfilled/rejected)同类:异步生命周期、操作状态机
- 落定(settled)同类:决议、完成、结束
二、语法与 API
- thenable同类:类 Promise 对象、鸭子类型
- Promise 链式调用同类:流式调用、管道流程
- .then() / .catch() / .finally()同类:回调处理器、完成钩子、清理函数
三、静态组合方法
- Promise.all同类:并行等待、全部成功、并发汇聚
- Promise.allSettled同类:容忍失败并行、结果收集、批量状态
- Promise.race同类:竞速、抢先完成、超时机制
- Promise.any同类:优先成功、多源备选、最快可用
- Promise.withResolvers同类:延迟决议、外部控制 Promise
- Promise.try同类:统一同步异步、安全执行包裹
四、模式与问题
- 回调地狱同类:嵌套金字塔、厄运金字塔
- Promise 构造反模式同类:多余包装、冗余封装
- 未处理 Promise 拒绝同类:未捕获异常、崩溃隐患
- 微任务时序同类:事件循环、任务队列、宏任务 / 微任务
五、上层抽象
- async/await同类:Promise 语法糖、线性异步写法
- 并行 / 串行 / 分批同类:并发控制、任务调度、限流
- 重试(Retry)同类:容错、退避重试、故障自动恢复
