闽公网安备 35020302035485号
// 假设有三个异步请求:获取用户信息、获取商品列表、获取消息通知
const fetchUserInfo = fetch('/api/user');
const fetchProducts = fetch('/api/products');
const fetchNotifications = fetch('/api/notifications');
Promise.all([fetchUserInfo, fetchProducts, fetchNotifications])
.then(([userInfo, products, notifications]) => {
// 只有当三个请求都成功时,才会进入这里
renderUserPage(userInfo, products, notifications);
})
.catch(error => {
// 如果任何一个请求失败,就会跳到这里
console.error('有一个请求失败了:', error);
showErrorPage('页面加载失败,请重试!');
});
场景分析: 如果 fetchNotifications(获取通知)的接口挂了,返回了 500 错误,那么即使 fetchUserInfo 和 fetchProducts 已经成功请求回来了数据,Promise.all 也会立刻终止,直接跳入 .catch 分支。// 成功状态
{ status: 'fulfilled', value: /* 成功的结果 */ }
// 失败状态
{ status: 'rejected', reason: /* 失败的原因(错误对象)*/ }
三、如何使用 Promise.allSettled?Promise.allSettled([fetchUserInfo, fetchProducts, fetchNotifications])
.then((results) => { // 注意:这里永远不会 catch
// results 是一个包含三个对象的数组
const userInfo = results[0].status === 'fulfilled' ? results[0].value : null;
const products = results[1].status === 'fulfilled' ? results[1].value : null;
const notifications = results[2].status === 'fulfilled' ? results[2].value : null;
// 我们可以针对每个结果进行精细化处理
if (userInfo && products) {
// 只要核心数据(用户和商品)还在,就渲染页面
renderUserPage(userInfo, products, notifications); // notifications 可能是 null
if (!notifications) {
showToast('通知获取失败,不影响主要功能');
}
} else {
// 如果核心数据缺失,再显示错误页
showErrorPage('核心数据加载失败');
}
});
// 不需要 .catch,因为它永远不会被触发
重构后的优势:信息完整:我们可以确切地知道每个任务的执行结果,并据此做出更细致的 UI 响应。
| 特性 | Promise.all | Promise.allSettled |
|---|---|---|
| 核心原则 | 全部或无一(All-or-nothing) | 有始有终(Complete-all) |
| 最终状态 | 如果有一个失败,则变为 Rejected | 永远变为 Fulfilled |
| 结果 | 所有成功的结果的数组 | 描述每个 Promise 结果的对象数组 |
| 适用场景 | 任务强依赖:多个任务必须全部成功才能进行下一步(例如:下单需要同时校验库存、优惠券、地址都有效) | 任务弱依赖:需要知道每个任务的最终状态,即使某些失败也不影响整体(例如:批量操作、页面初始化加载多个独立模块、上报日志) |