下面通过 “批量上传文件” 这个真实场景,演示如何使用 Promise.allSettled() 处理多个异步操作——即使部分文件上传失败,也能获取所有文件的上传结果(成功/失败状态),并最终统计结果、提示用户。
代码示例:批量文件上传(模拟)
// 1. 模拟单个文件上传的异步操作(返回Promise)
// 参数:fileName(文件名)、successRate(成功概率,0-1之间,用于模拟失败场景)
function uploadFile(fileName, successRate = 0.7) {
return new Promise((resolve, reject) => {
// 模拟上传耗时(1-3秒随机延迟,更贴近真实网络情况)
const delay = Math.random() * 2000 + 1000;
setTimeout(() => {
// 随机模拟成功/失败(根据successRate控制概率)
const isSuccess = Math.random() < successRate;
if (isSuccess) {
// 成功:返回上传结果(文件名、URL、大小)
resolve({
fileName,
status: "success",
fileUrl: `https://example.com/uploads/${
fileName}`,
size: Math.floor(Math.random() * 10) + 1 // 模拟文件大小(1-10MB)
});
} else {
// 失败:返回错误原因
reject(new Error(`文件 "${
fileName}" 上传失败:网络波动或文件损坏`));
}
}, delay);
});
}
// 2. 准备待上传的文件列表(模拟用户选择的5个文件)
const filesToUpload = [
"report_2024.pdf",
"avatar.png",
"meeting_notes.docx",
"data_backup.zip",
"presentation.pptx"
];
// 3. 生成所有文件的上传Promise数组
const uploadPromises = filesToUpload.map(fileName => {
// 为每个文件创建上传Promise(成功概率设为0.6,故意让部分文件失败)
return uploadFile(fileName, 0.6);
});
// 4. 使用Promise.allSettled()处理所有上传操作
console.log("开始批量上传文件...");
Promise.allSettled(uploadPromises)
.then(allResults => {
// 4.1 统计成功/失败数量
let successCount = 0;
let failCount = 0;
const successFiles = []; // 存储成功的文件信息
const failFiles = []; // 存储失败的文件信息
// 4.2 遍历所有结果,分类处理
allResults.forEach((result, index) => {
const fileName = filesToUpload[index]; // 对应原文件列表的文件名
if (result.status === "fulfilled") {
// 成功:收集信息,计数+1
successCount++;
successFiles.push(result.value);
} else {
// 失败:收集错误信息,计数+1
failCount++;
failFiles.push({
fileName,
errorMsg: result.reason.message // 提取错误原因
});
}
});
// 4.3 输出最终统计结果(用户友好的提示)
console.log("\n=== 批量上传完成 ===");
console.log(`总文件数:${
filesToUpload.length} | 成功:${
successCount} | 失败:${
failCount}`);
if (successFiles.length > 0) {
console.log("\n✅ 成功上传的文件:");
successFiles.forEach(file => {
console.log(`- ${
file.fileName}(${
file.size}MB):${
file.fileUrl}`);
});
}
if (failFiles.length > 0) {
console.log("\n❌ 上传失败的文件:");
failFiles.forEach(file => {
console.log(`- ${
file.fileName}:${
file.errorMsg}`);
});
}
})
.catch(error => {
// 注意:Promise.allSettled()本身不会reject,这里的catch几乎不会触发
console.error("批量上传过程中发生未知错误:", error.message);
});
代码解析:
uploadFile函数:
模拟单个文件的异步上传,通过随机延迟(1-3秒)和成功概率(successRate)模拟真实网络的不确定性,成功时返回文件上传信息,失败时抛出错误。生成 Promise 数组:
用map遍历待上传文件列表,为每个文件创建一个上传 Promise,组成uploadPromises数组(这是Promise.allSettled()的输入)。Promise.allSettled()核心逻辑:- 等待所有文件上传完成(无论成功或失败),不会因某个文件失败而提前终止。
- 接收的
allResults是一个数组,每个元素对应一个上传操作的结果,结构为:- 成功:
{ status: "fulfilled", value: 成功结果 } - 失败:
{ status: "rejected", reason: 错误对象 }
- 成功:
结果统计与展示:
遍历allResults,分类统计成功/失败的文件数量,提取关键信息(如成功文件的 URL、失败文件的错误原因),最终以用户友好的格式输出,方便后续处理(如重试失败文件)。
运行效果示例(每次运行可能不同,因随机因素):
开始批量上传文件...
=== 批量上传完成 ===
总文件数:5 | 成功:3 | 失败:2
✅ 成功上传的文件:
- report_2024.pdf(5MB):https://example.com/uploads/report_2024.pdf
- avatar.png(2MB):https://example.com/uploads/avatar.png
- presentation.pptx(8MB):https://example.com/uploads/presentation.pptx
❌ 上传失败的文件:
- meeting_notes.docx:文件 "meeting_notes.docx" 上传失败:网络波动或文件损坏
- data_backup.zip:文件 "data_backup.zip" 上传失败:网络波动或文件损坏
核心优势:
- 不“快速失败”:即使部分异步操作失败,也能获取所有操作的结果,适合需要“全量统计”的场景(如批量任务、报表生成)。
- 结果清晰:每个操作的状态和结果都被明确标记,便于后续分类处理(如重试失败任务、记录日志)。