Promise.all 是快速失败语义:任何一个 reject,整个就 reject,其他请求的结果直接丢弃,哪怕它们其实已经成功了。
场景
页面要同时拉 3 个接口,希望「哪个成功先渲染哪个,失败的给个降级」。用 Promise.all 会因为一个接口挂掉导致整页空白。
解法一:Promise.allSettled(最省事)
const results = await Promise.allSettled([fetchA(), fetchB(), fetchC()]);
const ok = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
const failed = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
永不 reject,每项告诉你 status 和 value/reason。
解法二:给每个 promise 兜底(想要默认值时)
const safe = p => p.catch(err => ({ error: err, data: null }));
const [a, b, c] = await Promise.all([fetchA(), fetchB(), fetchC()].map(safe));
还有两个兄弟别搞混
| 方法 | 语义 | 用途 |
|---|---|---|
Promise.all |
全成功才成功,一个失败即失败 | 强依赖,缺一不可 |
Promise.allSettled |
永不失败,返回每项状态 | 批量任务要统计结果 |
Promise.race |
第一个敲定(成功或失败)的胜出 | 超时控制 |
Promise.any |
第一个成功的胜出,全失败才失败 | 多源择优 |
用 race 做超时
const timeout = new Promise((_, rej) =>
setTimeout(() => rej(new Error('timeout')), 5000));
const data = await Promise.race([fetch(url), timeout]);
注意 race 只是让 await 提前返回,那个慢请求并没有被取消。真要取消得用 AbortController:
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5000);
const res = await fetch(url, { signal: ctrl.signal });
楼主 · 2026-09-28 13:21 · 浏览 4

