JS中Promise.all 和 Promise.allsettled区别小结
作者:代码猎人
本文主要介绍了JS中Promise.all 和 Promise.allsettled区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
核心区别对比表
| 特性 | Promise.all | Promise.allSettled |
|---|---|---|
| 成功条件 | 所有 Promise 都成功 | 所有 Promise 都完成(无论成功失败) |
| 失败条件 | 任何一个 Promise 失败就立即失败 | 永远不会失败 |
| 返回值 | 成功值数组 | 状态对象数组 |
| 设计目的 | 需要所有结果都成功才能继续 | 需要知道每个 Promise 的最终状态 |
| ES版本 | ES6 (2015) | ES2020 |
| 使用场景 | 并行依赖的操作 | 独立的并行操作 |
详细对比
1.行为差异
Promise.all - 全有或全无
const p1 = Promise.resolve('成功1');
const p2 = Promise.reject('错误2'); // 这个会失败
const p3 = Promise.resolve('成功3');
Promise.all([p1, p2, p3])
.then(results => {
console.log('全部成功:', results);
})
.catch(error => {
console.log('有一个失败:', error); // 输出: "错误2"
// p1和p3的结果被丢弃!
});
- 只要有一个失败,立即失败
- 其他 Promise 的结果会被丢弃
Promise.allSettled - 全部完成
const p1 = Promise.resolve('成功1');
const p2 = Promise.reject('错误2');
const p3 = Promise.resolve('成功3');
Promise.allSettled([p1, p2, p3])
.then(results => {
console.log('全部完成:');
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`p${index + 1}: 成功 - ${result.value}`);
} else {
console.log(`p${index + 1}: 失败 - ${result.reason}`);
}
});
});
// 输出:
// 全部完成:
// p1: 成功 - 成功1
// p2: 失败 - 错误2
// p3: 成功 - 成功3
- 等待所有 Promise 完成
- 返回每个 Promise 的完整状态信息
2.返回值结构不同
Promise.all 返回值
// 成功时返回: [value1, value2, ...]
Promise.all([Promise.resolve(1), Promise.resolve(2)])
.then(values => console.log(values)); // [1, 2]
// 失败时返回: 第一个错误
Promise.all([Promise.resolve(1), Promise.reject('错误')])
.catch(error => console.log(error)); // "错误"
Promise.allSettled 返回值
Promise.allSettled([
Promise.resolve(1),
Promise.reject('错误'),
Promise.resolve(3)
])
.then(results => {
console.log(results);
/*
[
{ status: 'fulfilled', value: 1 },
{ status: 'rejected', reason: '错误' },
{ status: 'fulfilled', value: 3 }
]
*/
});
3.实际应用场景
适合 Promise.all 的场景
// 场景1: 需要所有数据才能渲染页面
async function loadDashboard() {
try {
const [user, orders, notifications] = await Promise.all([
fetchUser(),
fetchOrders(),
fetchNotifications()
]);
// 所有数据都成功才渲染
renderDashboard({ user, orders, notifications });
} catch (error) {
// 任何一个失败就显示错误页面
showErrorPage('加载数据失败');
}
}
// 场景2: 并行执行但有依赖关系
async function processOrder(orderId) {
const [order, inventory, payment] = await Promise.all([
getOrder(orderId),
checkInventory(orderId),
verifyPayment(orderId)
]);
// 三个检查都通过才能继续
return { order, inventory, payment };
}
适合 Promise.allSettled 的场景
// 场景1: 批量操作,需要知道每个结果
async function sendNotifications(users) {
const results = await Promise.allSettled(
users.map(user => sendNotification(user))
);
const successful = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
const failed = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
console.log(`发送成功: ${successful.length}, 失败: ${failed.length}`);
return { successful, failed };
}
// 场景2: 多源数据获取,哪个快用哪个
async function getDataFromMultipleSources() {
const results = await Promise.allSettled([
fetchFromPrimaryAPI().catch(() => null), // 主API
fetchFromBackupAPI1().catch(() => null), // 备份API1
fetchFromBackupAPI2().catch(() => null) // 备份API2
]);
// 使用第一个成功的结果
for (const result of results) {
if (result.status === 'fulfilled' && result.value) {
return result.value;
}
}
throw new Error('所有数据源都失败了');
}
// 场景3: 清理操作,无论单个成功失败都要继续
async function cleanupResources(resources) {
const cleanupResults = await Promise.allSettled(
resources.map(resource => resource.cleanup())
);
// 记录所有清理结果,但不中断流程
logCleanupResults(cleanupResults);
}
4.错误处理差异
// 使用 Promise.all 的错误处理
Promise.all([task1(), task2(), task3()])
.then(([result1, result2, result3]) => {
// 成功处理
})
.catch(error => {
// 任何一个失败都会到这里
// 但不知道哪些成功了,哪些失败了
console.error('某个任务失败:', error);
});
// 使用 Promise.allSettled 的错误处理
Promise.allSettled([task1(), task2(), task3()])
.then(results => {
const errors = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
const successes = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
if (errors.length > 0) {
console.log(`${errors.length} 个任务失败,但继续处理成功的`);
// 可以继续处理 successes
}
return { successes, errors };
});
5.互相模拟实现
// 用 Promise.allSettled 模拟 Promise.all
function promiseAll(promises) {
return Promise.allSettled(promises)
.then(results => {
const rejected = results.find(r => r.status === 'rejected');
if (rejected) {
throw rejected.reason; // 抛出第一个错误
}
return results.map(r => r.value); // 返回所有值
});
}
// 用 Promise.all 模拟 Promise.allSettled(不完美)
function promiseAllSettled(promises) {
// 为每个 Promise 添加错误处理,确保不会抛出
const wrappedPromises = promises.map(p =>
Promise.resolve(p).then(
value => ({ status: 'fulfilled', value }),
reason => ({ status: 'rejected', reason })
)
);
return Promise.all(wrappedPromises);
}
总结选择建议
使用Promise.all当:
- 所有 Promise 必须都成功才能继续
- 操作有强依赖关系
- 一个失败意味着整个操作失败
- 需要快速失败机制
使用Promise.allSettled当:
- 需要知道每个 Promise 的最终状态
- 操作是独立的,一个失败不影响其他
- 需要收集所有结果(成功和失败)
- 实现降级机制或备用方案
- 执行清理或日志记录操作
简单记忆:
- Promise.all = "全部成功才算成功"
- Promise.allSettled = "全部完成就是成功"
到此这篇关于JS中Promise.all 和 Promise.allsettled区别小结的文章就介绍到这了,更多相关JS中Promise.all 和 Promise.allsettled内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
