前言
在处理多个并发请求的时候,大部分时候我们会选择用Promise.all。
首先,我们先来看看如何实现一个Promise.all
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
if (Array.isArray(promises)) {
let result = []; // 存储结果
let count = 0; // 计数器
// 如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise
if (promises.length === 0) {
return resolve(promises);
}
promises.forEach((item, index) => {
// 判断参数是否为promise与thenable对象
if (item instanceof Promise || (item instanceof Object && 'then' in item)) {
item.then(
value => {
count++;
result[index] = value;
count === promises.length && resolve(result);
},
reason => {
reject(reason);
}
)
} else {
count++;
result[index] = item;
count === promises.length && resolve(result);
}
})
} else {
return reject(new TypeError('Argument is not iterable'))
}
})
}
从实现的code可以看出:
- 该方法指当所有在可迭代参数中的
promise已完成,或者第一个传递的 promise(指 reject)失败时,返回 promise。 - 当其中任何一个被拒绝的话。
Promise.all([..])就会立即被拒绝,并丢弃来自其他所有promise的全部结果。 promise.all中任何一个promise出现错误的时候都会执行reject,导致其它正常返回的数据也无法使用。
如何让Promise.all在抛出异常后依然有效呢?
方法一
let p1 = new Promise((resolve, reject) => {
resolve("p1");
});
let p2 = new Promise((resolve, reject) => {
resolve("p2");
});
let p3 = new Promise((resolve, reject) => {
reject("p3");
});
Promise.all([p1, p2, p3].map(p => p instanceof Promise? p.catch(e => e):Promise.resolve(p)))
.then(values => {
console.log(values);
}).catch(err => {
console.log(err);
})
输出:["p1","p2","p3"]
解析
- 一、我们知道
Promise中resolve过后始终会被then中第一个参数获取到。 - 二、并且
Promise链式调用onFulfilled成功回调,onRejected失败回调后的返回值可以返回一个Promise实例或者其他类型的值(最终会被Promise.resolve包装)。 - 利用这两点,就可以让
Promise.all接收的数组中全部经过catch后返回。现在所有的值都是resolve成功的状态了。最后Promise.all也能成功捕获到所有的状态。 - 如果不了解
Promise相关规范的可以移步Promise A+ 规范,这里就不多介绍了。
方法二
使用ES2020(即 ES11)Promise新增的静态方法allSettled即 Promise.allSettled 替代 Promise.all()。
let p1 = new Promise((resolve, reject) => {
resolve("p1");
});
let p2 = new Promise((resolve, reject) => {
resolve("p2");
});
let p3 = new Promise((resolve, reject) => {
reject("p3");
});
Promise.allSettled ([p1, p2, p3])
.then(values => {
console.log(values);
}).catch(err => {
console.log(err);
})
输出:
[
{
"status": "fulfilled",
"value": "p1"
},
{
"status": "fulfilled",
"value": "p2"
},
{
"status": "rejected",
"reason": "p3"
}
]
Promise.allSettled()方法返回一个promise,该promise在所有给定的promise已被解析或被拒绝后解析,并且每个对象都描述每个promise的结果。
最后
本文就讲到这里,各位看官如果文中有错希望不惜吝啬欢迎指出!