最新的EcmaScript标准推出了Promise.allSettled这个标准API方法,弥补了Promise.all不适应的一些场景。和all一样,allSettled也是若干个异步promise任务并发执行,不同的是,allSettled不会因为某个promise失败而导致所有promise停止运行(这是all方法的痛点)。allSettled会等到所有promise独立地运行结束,无论其结果是resolved还是rejected。所以一个promise完整的状态关系如下图:
虽然标准已经支持了,但我们还是手写一个Promise.allSettled的封装来学习一下,以防老旧浏览器不支持:
Promise.allSettled =
Promise.allSettled ||
function(arr) {
let P = this;
return new P(function(resolve, reject) {
if (Object.prototype.toString.call(arr) !== '[object Array]') {
return reject(
new TypeError(
typeof arr +
' ' +
arr +
' ' +
' is not iterable(cannot read property Symbol(Symbol.iterator))'
)
);
}
let args = Array.prototype.slice.call(arr);
if (args.length === 0) return resolve([]);
let arrCount = args.length;
function resolvePromise(index, value) {
if (typeof value === 'object') {
let then = value.then;
if (typeof then === 'function') {
then.call(
value,
function(val) {
args[index] = { status: 'fulfilled', value: val };
if (--arrCount === 0) {
resolve(args);
}
},
function(e) {
args[index] = { status: 'rejected', reason: e };
if (--arrCount === 0) {
resolve(args);
}
}
);
}
}
}
for (let i = 0; i < args.length; i++) {
resolvePromise(i, args[i]);
}
});
};
Promise.allSettled官方文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
<完>