02Promise

回调地狱(callback hell)的终结者。Promise 用一个「承诺对象」 表示异步结果,链式 .then 横向展开代码,错误用 .catch 统一接。 这是 fetch、axios、async/await 的共同底座。

约 15 分钟 4 个动手实验 异步核心

一、三种状态

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 秒超时就失败」。