手写Promise.all()

74 阅读2分钟

理解Promise.all()

Promise.all() 静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise\underline{\text{Promise}}。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。

  • 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
  • Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

    const p = Promise.all([p1, p2, p3]);

p的状态由p1p2p3决定,分成两种情况。

  1. 只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。
  2. 只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.all()可以确定所有请求都成功了,但是只要有一个请求失败,它就会报错,而不管另外的请求是否结束。


手写 Promise.all

Promise.myAll = function (proms) {
    // 创建变量保存构造器里的resolve, reject
    let res, rej;
    const p = new Promise((resolve, reject) => {
        res = resolve;
        rej = reject;
    });
 
    let count = 0;
    const result = [];
    let i = 0;
    let fulfillCount = 0;// 完成的Promise数量
    // 可迭代对象一定可以使用for of循环
    for (const prom of proms) {
        const index = i;
        i++;
        count++;
        Promise.resolve(prom).then((data) => {
            // 1.汇总顺序应该与传入顺序一致,所以需要定义变量对应传入下标
            result[index] = data;
            
            // 2.标记已完成的Promise
            fulfillCount++;
            if (fulfillCount === count) {
                res(result);
            }
        }, rej);
    }
    // 可能是Set集合,所以不能使用proms.length(size)===0来判断传入[]
    // 需要创建
    if (count === 0) {
        res([]);
    }
    return p;
};

参照文章