JavaScript Guidebook

JavaScript 完全知识体系

Promise.allSettled

⭐️ ES2020(ES11)新特性

Promise.allSettled 方法返回一个在所有给定的 Promise 都已经 fullfilledrejected 后的 Promise,并带有一个对象数组,每个对象表示对应的 Promise 结果。

当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个 Promise 的结果时,通常使用它。

语法

语法:

Promise.allSettled(iterable);

类型声明:

interface PromiseFulfilledResult<T> {
status: 'fulfilled';
value: T;
}
interface PromiseRejectedResult {
status: 'rejected';
reason: any;
}
type PromiseSettledResult<T> = PromiseFulfilledResult<T> | PromiseRejectedResult;
interface PromiseConstructor {
allSettled<T extends readonly unknown[] | readonly [unknown]>(
values: T
): Promise<
{ -readonly [P in keyof T]: PromiseSettledResult<T[P] extends PromiseLike<infer U> ? U : T[P]> }
>;
allSettled<T>(
values: Iterable<T>
): Promise<PromiseSettledResult<T extends PromiseLike<infer U> ? U : T>[]>;
}

参数说明:

参数说明类型
iterable见下方any

根据传入参数的不同,会有不同的响应效果:

  • 空的具备 Iterator 接口的对象,返回状态为 Fulfilled 的 Promise
  • 不包含任何 Promise,返回异步完成的 Promise
  • 其他情况,返回状态为 Pending 的 Promise

  • 参数 iterable 必须具备 Iterator 接口,且每个成员都是 Promise 实例
  • 如果 iterable 内每个成员都不是 Promise 实例,会先调用 Promise.resolve 将每个成员转化为 Promise 实例,再进一步处理

方法描述

对于 Promise.allSettled 执行集合中的每个 Promise 都已经完成后,无论时成功(fulfiiled)或是拒绝(rejected),未决议的 Promise 将被异步完成。那时,所返回的 Promise 的处理器将传入一个数组作为输入,该数组包含原始 Promise 集合中每个 Promise 的结果。

对于每个结果对象,都有一个 status 字段。

  • 如果值为 fulfilled,则结果对象上存在一个 value
  • 如果值为 rejected,则存在一个 reason

valuereason 分别反映了每个 Promise 决议(或拒绝)的值。

代码示例

应用场景:

  • 同时上传多张图片,实现异步并发(例如使用阿里云 OSS 同时批量上传多张图片)

基本用法

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))
);
// 结果:
// fulfilled
// rejected

异步并发

let files = [{ file: new File() }, { file: new File() }];
const ossConfig = {
accessKeyId: 'xxx',
accessKeySecret: 'xxx',
stsToken: 'xxx',
bucket: 'xxx',
region: xxx'',
};
function uploadFile(file) {
return new Promise((resolve, reject) => {
try {
const filePath = genPath('');
const client = new OSS(ossConfig);
client.put(filePath, file).then(res => {
if (res?.res?.status === 200) {
resolve(res.url);
} else {
reject('上传失败');
}
});
} catch (err) {
reject(err);
}
});
}
async function uploadFiles(files) {
const promises = [],
urls = [];
try {
for (const item of files) {
const promise = uploadFile(item.file);
promises.push(promise);
}
const result = await Promise.allSettled(promises);
urls = result.reduce((acc, item) => {
if (item.status === 'fulfilled') {
acc.push({ url: item.value });
}
return acc;
}, []);
} catch (err) {
console.log(err);
}
return urls;
}

参考资料