Promse.all 与 Promise.allSettled
背景
多个promise需要都正确返回的时候处理逻辑,使用了promise.all
问题
但是比如多个promise中有一个抛出错误,那么整体就立即catch,不管剩余的其他promise有没有执行完
需求
多个promise 如果至少一个报错,需要都执行完毕,再catch到error,而不是catch到一个error就立即抛出来,不管其他结果
解决办法一
使用最新的API, Promise.allSettled
MDN
片段一
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) =>setTimeout(reject, 100, "foo"),
);
const promises = [promise1, promise2];Promise.allSettled(promises).then((results) =>results.forEach((result) => console.log(result.status)),
);// Expected output:
// "fulfilled"
// "rejected"
片段二
Promise.allSettled(allPromises).then((results) => {const successCount = results.filter(r => r.status === 'fulfilled').length;const failureCount = results.filter(r => r.status === 'rejected').length;console.log(`成功: ${successCount}, 失败: ${failureCount}`);if (failureCount === 0) {console.log('成功')} else {console.log(`成功${successCount}个,失败${failureCount}个`);reject(new Error('部分失败'));}
}).finally(() => {
});
解决办法二
一些老环境不支持最新API,手动实现
手动实现一
const results = [];
let completedCount = 0;
const totalCount = allPromises.length;allPromises.forEach((promise, index) => {promise.then((res) => {results[index] = { success: true, data: res };}).catch((err) => {results[index] = { success: false, error: err };}).finally(() => {completedCount++;if (completedCount === totalCount) {// 所有接口都完成了const successCount = results.filter(r => r.success).length;const failureCount = results.filter(r => !r.success).length;console.log(`成功: ${successCount}, 失败: ${failureCount}`);if (failureCount === 0) {console.log('成功')} else {console.log(`成功${successCount}个,失败${failureCount}个`);reject(new Error('部分失败'));}}});
});
手动实现二
// 手动实现 Promise.allSettled
function promiseAllSettled(promises) {return Promise.all(promises.map(promise =>Promise.resolve(promise).then(value => ({ status: 'fulfilled', value })).catch(reason => ({ status: 'rejected', reason }))));
}// 使用方式
promiseAllSettled(allPromises).then((results) => {const successCount = results.filter(r => r.status === 'fulfilled').length;const failureCount = results.filter(r => r.status === 'rejected').length;console.log(`成功: ${successCount}, 失败: ${failureCount}`);if (failureCount === 0) {console.log('成功')} else {console.log(`成功${successCount}个,失败${failureCount}个`);reject(new Error('部分失败'));}
}).finally(() => {this.isLoading = false;
});