在 JavaScript 中,Promise.all允许我们并行地处理多个Promise,并且在所有Promise都成功完成或其中任何一个失败时才返回结果。
1. 什么是Promise.all?
Promise.all是一个静态方法,它接收一个Promise对象数组作为参数,并返回一个新的Promise对象。这个新的Promise对象在传入的所有Promise对象都解决(resolve)时解决,或者其中一个Promise对象被拒绝(reject)时被拒绝。
2. 使用Promise.all的场景
2.1 并行请求
当我们需要同时发起多个异步请求,并且需要等待所有请求完成后再执行后续操作时,Promise.all就非常有用了。比如,在前端开发中,我们可能需要从不同的接口获取数据,然后在页面上展示这些数据,而且我们希望所有数据都加载完毕后再渲染页面,这时就可以使用Promise.all来管理多个异步请求。
2.2 同时处理多个文件上传
另一个常见的场景是同时处理多个文件上传。在Web开发中,我们经常需要让用户上传多个文件,然后将这些文件上传到服务器。使用Promise.all可以很方便地等待所有文件都上传成功后再执行后续操作,比如将上传成功后返回的文件ID与其他表单数据一起提交给后端。
3. Promise.all的使用示例
示例1,演示了如何使用Promise.all来并行处理多个异步请求:
const promises = [
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
fetch('https://api.example.com/data3')
];
Promise.all(promises)
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => {
// 处理返回的数据
console.log('所有数据加载成功', data);
})
.catch(error => {
// 处理错误
console.error('发生错误', error);
});
在这个示例中,我们创建了一个包含多个异步请求的Promise数组promises,并将它们传递给Promise.all。然后,我们使用.then链来处理所有请求的响应,确保在所有请求完成后再处理返回的数据。
示例2,场景:逐一上传文件,获取文件id。待全部上传完毕后,将ids和form表单一起上传。
submitFnc(form, fileList) {
uni.showLoading({ title: "上传中…", mask: true });
console.log("form", form); // form是一个对象表单
console.log("files", fileList); // fileList是一个文件列表
let ids = []; // 用于存储每个文件上传后返回的 id
let uploadPromises = []; // 创建一个 Promise 对象数组,用于存储每个文件上传的 Promise 对象
// 循环遍历 fileList,为每个文件创建上传 Promise 对象并存储到数组中
for (let i = 0; i < fileList.length; i++) {
let file = fileList[i];
let uploadPromise = new Promise((resolve, reject) => {
uni.uploadFile({
url: 'https://example.com/upload', // 上传文件的接口地址
filePath: file.path, // 要上传文件资源的路径
name: 'file', // 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容
formData: {}, // HTTP 请求中其他额外的formData
success: (uploadFileRes) => { // 上传成功后的回调
console.log(`第 ' + (${i} + 1) + ' 个文件(${file.name})上传成功.`, uploadFileRes.data);
let id = uploadFileRes.data.id; // 假设服务器返回的 id 存在 data.id 中
ids.push(id); // 将返回的 id 存储到 ids 数组中
resolve(); // 将 Promise 对象标记为成功状态
},
fail: (error) => { // 上传失败后的回调
console.error(`第 ' + (${i} + 1) + ' 个文件(${file.name})上传失败.`, error);
reject(error); // 将 Promise 对象标记为失败状态
}
});
});
uploadPromises.push(uploadPromise); // 将上传 Promise 对象存储到数组中
}
// 使用 Promise.all 等待所有文件上传完成
Promise.all(uploadPromises)
.then(() => {
// 所有文件上传完成后
接口({ ...this.baseFormData, ids: ids }).then((res) => {
console.log("提交成功", res);
this.showMessage("success", "提交成功");
this.reset();
})
.catch((err) => {
console.error("提交失败", err);
this.showMessage("error", "提交失败");
})
.finally(() => {
uni.hideLoading();
})
})
.catch((error) => {
uni.hideLoading();
this.showMessage("error", "文件上传失败, 请重试");
console.error('文件上传失败', error);
});
},