02Promise
回调地狱(callback hell)的终结者。Promise 用一个「承诺对象」
表示异步结果,链式 .then 横向展开代码,错误用 .catch 统一接。
这是 fetch、axios、async/await 的共同底座。
一、三种状态
pending
进行中,还没出结果。创建后默认状态。
fulfilled
成功完成,携带 value。触发 .then。
rejected
失败完成,携带 reason。触发 .catch。
状态只会变一次:pending → fulfilled 或 pending → rejected。
之后再调 resolve/reject 无效。这是 Promise「不可变」的保证。
二、创建与消费
造一个「模拟请求」Promise:点成功按钮 resolve,点失败按钮 reject,看 then/catch 分支
点按钮
三、链式调用:扁平化回调地狱
.then 会返回一个新的 Promise,所以可以一直接下去。
回调里 return 的值会传给下一个 then;return 一个 Promise 则会等它完成。
三步链式:获取用户 → 获取订单 → 获取详情,点按钮看数据怎么一层层传下去
点按钮
四、错误处理:catch 的位置
| 写法 | 行为 | 建议 |
|---|---|---|
then(onFul).catch(onRej) |
then 里抛错也会进 catch | 推荐,一个 catch 接全部 |
then(onFul, onRej) |
只接「上一个 Promise」的失败 | then 里新抛的错接不住 |
…catch().then() |
catch 后面的 then 能继续 | 可做降级后继续流程 |
finally() |
成败都跑,不改结果 | 关 loading、清理资源 |
没有
catch 的失败 Promise 会变成「未处理的 rejection」,
浏览器 Console 会报 Uncaught (in promise)。生产代码一定要有 catch。五、并发:all / race / allSettled / any
| API | 何时完成 | 失败时 | 场景 |
|---|---|---|---|
Promise.all |
全部成功 | 任一失败立即 reject | 页面多个接口都必须到齐 |
Promise.allSettled |
全部结束(成败皆可) | 不 reject,返回状态数组 | 批量任务,失败的跳过 |
Promise.race |
第一个结束(成败皆可) | 第一个 reject 就 reject | 超时控制、取最快源 |
Promise.any |
第一个成功 | 全部失败才 reject | 多镜像源取一个可用的 |
Promise.all 并发:三个模拟请求同时发出,全部完成后一次拿到数组
点按钮
六、封装异步:把回调 API 变成 Promise
看到「最后参数是回调」的老 API,就可以用
new Promise 包一层,让后续代码统一走 then/await。七、Promise 是微任务
回顾上一课:.then 回调进微任务队列,
会在当前同步代码与微任务清空后、下一个宏任务之前执行。
这就是为什么 then 比 setTimeout 0 更「快」。
八、本章小结
- 三态:pending → fulfilled / rejected,只变一次。
new Promise((resolve, reject) => …)创建;then / catch / finally消费。- 链式
then可以return值或另一个 Promise,实现扁平异步流。 - 推荐
then(ful).catch(rej)一个 catch 接全部;必写 catch。 - 并发四件套:
all全成功、allSettled全结束、race第一个结束、any第一个成功。 - then 回调是微任务,优先于 setTimeout。
动手练习:
① 把
setTimeout 包装成 wait(ms) 的 Promise;
② 用 Promise.all 同时请求 3 个模拟接口并渲染列表;
③ 用 Promise.race 实现「2 秒超时就失败」。