简介:
-
Promise.all是JavaScript中一种用于处理多个Promise对象的方法,该方法接收一个数组作为参数,并返回一个新的Promise对象。
-
这个新的对象会在所有Promise对象都成功解析后解析,解析的结果是一个数组,包含了所有Promise对象解析后的结果。
-
解析时如果任何一个Promise对象失败,则这个新的Promise实例会立即失败,并返回第一个失败的Promise对象的错误信息。
-
Promise.all不会改变原有的Promise对象的状态,原有的 Promise 对象仍会按照自己的状态(fulfilled或rejected)进行解析。
那么Promise.all的具体实现过程是怎样的?今天来记录学习下,话不多说,直接上代码和注释,
// 手写Promise.all方法
Promise.myPromiseAll = function (props) {
// 这里定义res、rej变量,在Promsie内部赋值,
// 这样外部就可以直接调用res()、rej()方法
let res, rej;
// 这里定义promise1,用于最后返回最终状态
const promise1 = new Promise((resolve, reject) => {
res = resolve;
rej = reject;
});
//定义i 表示Promise对象的数量
let i = 0;
// 定义result 用于存储每个成功Promise的结果
const result = [];
//定义fulfilled 用于追踪已完成的Promise数量
let fulfilled = 0;
// 这里不能使用.length判断props数组长度,因为他有可能是一些别的可迭代对象,
// 所以这里使用for of循环Promise的参数props,for of可以循环任意的可迭代对象
for (const item of props) {
// 这里保存的数据下标index,用于赋值成功后的data数据,形成闭包环境
const index = i;
// 这里每循环一次i加1,表示Promise数量
i++;
// 这里循环拿到的不一定是一个Promise,所以使用Promise.resolve包装一下,
// 然后处理成功和失败的状态
Promise.resolve(item).then((data) => {
// 这里需要考虑到Promise成功时需要做到什么?1、2、
// 1、完成的数据汇总到一个数组,最终结果
// 在上面定义result,于存储每个成功Promise的结果,
// 这里不能使用push方法,因为我们需要返回的数据是传递的顺序,不是完成的顺序
// 所以这里根据下标赋值成功后的data数据
result[index] = data;
// 2、判定是否全部完成
// 这里在上面定义fulfilled,记录每次完成fulfilled数量加1
fulfilled++;
// 这里判断fulfilled完成的数量和Promise数量相等时表示结束,
// 把数据result给res
if (fulfilled === i) { res(result); }
// 这里如果失败,直接调用失败的方法,因为状态一旦确定就无法更改
}, rej)
// 因为这里是异步代码,运行时循环已经结束,所以i代表的一定是整体的数量
}
// 这里循环完成,判断i如果等于0,表示没有传递任何Promise参数
// 直接给一个空数组
if (i === 0) { res([]); }
// 最后直接返回最终状态promise1
return promise1;
}
Promise.myPromiseAll([]).then((res) => {
console.log(res);
}, (err) => {
console.log("err", err);
})
// 输出 []
Promise.myPromiseAll([1, 2, 3]).then((res) => {
console.log(res);
}, (err) => {
console.log("err", err);
})
// 输出 [1, 2, 3]
Promise.myPromiseAll([1, 2, 3, Promise.reject(456)]).then((res) => {
console.log(res);
}, (err) => {
console.log("error", err);
})
// 输出 error 456
Promise.myPromiseAll([1, 2, 3, Promise.resolve(456)]).then((res) => {
console.log(res);
}, (err) => {
console.log("err", err);
})
// 输出 [ 1, 2, 3, 456 ]