我有一支技术全面、经验丰富的小型团队,专注高效交付中等规模外包项目,有需要外包项目的可以联系我
引子
同时并发调用一堆 API,既迅速 又优雅 。把所有请求塞进 Promise.all
,点一下部署,你会觉得自己就是 JavaScript 摇滚明星。 然而,一个细小的失败就足以拖垮全局------我就亲历了这场事故。
这篇文章会把 Promise.all
和 Promise.allSettled
的关键差异讲清楚,并解释我如何因为切换到后者,躲过了一次"无声灾难"。
场景设定
我在做一个仪表盘,需要从多个微服务并发拉数据:
go
const [user, orders, notifications] = await Promise.all([
getUser(),
getOrders(),
getNotifications(),
]);
一切都很顺利------直到某个接口开始间歇性失败 。 当其中任意一个 Promise 拒绝时,整组调用立刻崩溃:没有兜底、没有部分数据、只有报错。
轮到 Promise.allSettled
登场
与"有一个失败就整体拒绝 "的 Promise.all
不同,Promise.allSettled
会等全部 Promise 结束,并返回每一项的状态与结果/原因。
go
const results = await Promise.allSettled([
getUser(),
getOrders(),
getNotifications(),
]);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('Success:', result.value);
} else {
console.warn('Failed:', result.reason);
}
});
这样我就可以:
-
渲染部分数据(谁成功就先展示谁);
-
标注失败模块(告诉用户哪个小部件挂了);
-
有选择地重试(只重试失败的那几项)。
因此,应用的韧性 更强,用户体验也更友好 。尽管如此,要注意状态分支处理更细,代码上需要明确区分 fulfilled / rejected;与此同时,日志与监控也要跟上,避免悄悄失败。
要点小结
-
Promise.all
:只要有一个失败 就立刻 reject,其余结果不再等待。 -
Promise.allSettled
:全部等待 完成,返回每一项 的{ status, value | reason }
。 -
使用建议:
-
-
当所有步骤必须成功 (如登录流程的多步校验、事务性写入)→ 用 **
Promise.all
**,失败要尽快中断。 -
当允许部分失败 (如仪表盘多部件、侧边小组件、可降级内容加载)→ 用 **
Promise.allSettled
**,容错更合适。
-
进一步的实战提示
-
选择性重试
goconst results = await Promise.allSettled(tasks); const failed = results .map((r, i) => [r, i]) .filter(([r]) => r.status === 'rejected') .map(([, i]) => tasks[i]); if (failed.length) { // 退避重试或队列重放 await Promise.allSettled(failed.map(backoffRetry)); }
-
保持响应可用 即使部分失败,也返回带缺口的 UI(骨架屏/占位符),并附带"刷新/重试"入口,因此用户不会看到空白或整页报错。
-
区分"硬必需"与"软可选" 把关键数据(必须成功)与附加数据(可失败)拆分 ,前者走
Promise.all
,后者走Promise.allSettled
,从而保证核心路径确定性。
✅ 结语
JavaScript 给了我们强大的并发原语;在恰当时机选用恰当工具 ,才是高级开发者的分水岭。 如果你的应用频繁并行请求、或依赖并不稳 的端点,不妨试试 Promise.allSettled
------也许它也会拯救你的 API。
全栈AI·探索:涵盖动效、React Hooks、Vue 技巧、LLM 应用、Python 脚本等专栏,案例驱动实战学习,点击二维码了解更多详情。

最后: