手动实现Promise.all

497 阅读2分钟

Promise.all功能分析:

  1. 方法接受一个数组(可以不是数组,但须具有Iterator接口)作为参数;
  2. 方法返回一个新的Promise实例;
  3. 数组成员中不是Promise实例的会转成Promise实例;
  4. 当数组成员状态都变成fulfilled时,返回的Promise实例状态也变成fulfilled,数组成员的结果按顺序组成新数组,作为返回的Promise实例的结果;
  5. 当数组任意一个成员状态变成时rejected时,返回的Promise实例状态变成rejected,第一个状态变成rejected的结果作为返回的Promise实例的结果。

实现(新方法命名为promiseAll):

根据功能第1、2点——接收一个数组参数,返回一个Promise实例

const promiseAll = (promises) => {
  return new Promise((resolve, reject) => {
    
  });
}

遍历数组。因为参数可以不是数组,但须具有Iterator接口,所以使用for of循环。根据功能第3点,使用Promise.resolve处理数组成员

const promiseAll = (promises) => {
  return new Promise((resolve, reject) => {
    for (const promise of promises) {
      Promise
        .resolve(promise)
    }
  });
};

根据功能第4点,声明一个变量responses作为新数组存储数组成员fulfilled的结果。注意responses的成员顺序与原数组顺序保持一致。并在所有数组成员都变成fulfilled状态时resolve(responses)

const promiseAll = (proms) => {
  return new Promise((resolve, reject) => {
    const promises = Array.from(proms);
    const promiseLength = promises.length;
    const responses = new Array(promiseLength);
    // fulfilled状态的数量
    let fulfilledQuantity = 0;

    for (const [i, promise] of promises.entries()) {
      Promise
        .resolve(promise)
        .then((res) => {
          responses[i] = res;
          fulfilledQuantity++;
          
          if (fulfilledQuantity === promiseLength) {
            resolve(responses)
          }
        })
    }
  });
};

根据功能第5点,任意一个成员状态变成时rejected时,reject这个成员结果。下面是代码最终结果

const promiseAll = (promises) => {
  return new Promise((resolve, reject) => {
    const promiseLength = promises.length;
    const responses = new Array(promiseLength);
    // fulfilled状态的数量
    let fulfilledQuantity = 0;

    for (const [i, promise] of promises.entries()) {
      Promise
        .resolve(promise)
        .then((res) => {
          responses[i] = res;
          fulfilledQuantity++;
          
          if (fulfilledQuantity === promiseLength) {
            resolve(responses)
          }
        })
        .catch((error) => {
          reject(error)
        });
    }
  });
};

测试

const p1 = new Promise((resolve, reject) => {
  resolve('p1')
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p2')
  }, 1000);
});

const p3 = new Promise((resolve, reject) => {
  reject('p3 error')
});

promiseAll([p1, p2])
  .then((res) => {
    console.log(res)
  })
  .catch((err) => {
    console.log(err)
  });

promiseAll([p1, p2, p3])
  .then((res) => {
    console.log(res)
  })
  .catch((err) => {
    console.log(err)
  });

运行结果为: 先打印“p3 error”,1秒后打印“[ 'p1', 'p2' ]”,符合预期结果。