首页 > 解决方案 > 我的 Promise.all() 实现有什么问题?

问题描述

我正在尝试编写我的Promise.all()函数。它应该重复本机Promise.all()方法的功能。

如果数组中只有 Promise,则代码可以正常工作,如果数组包含 Promise 以外的内容,则可能会出现问题。

下面是一个执行示例:

const p1 = Promise.resolve(3);

const p2 = 1337;

const p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 10000, 'foo');
});

promiseAll([p1, p3, p3]).then(values => console.log(values)); // [3, 1337, "foo"]

这是我的代码:

const promiseAll = promises => new Promise((resolve, reject) => {
  if (promises.length === 0) { resolve([]); }
  const results = [];

  let resolved = 0;

  promises.forEach(promise => {
    if (!(promise instanceof Promise)) {
      Promise.resolve(promise).then(data => results.push(data));
    }
    promise.then(result => {
      results.push(result);
      resolved += 1;
      if (resolved === promises.length) {
        resolve(results);
      }
    }, error => reject(error));
  });
});

问题是什么?

标签: javascriptpromise

解决方案


您的实施存在两个主要问题:

  1. forEach()方法内部,您有一个检查:promise instanceof Promise. 如果这个检查是假的,你打电话Promise.resolve()BUT 然后你也打电话promise.then(...); 您可能打算在块then()内调用方法else

  2. Promise.all()维持秩序 - 你的实施没有。results这是因为您只需按照解决承诺的顺序将承诺结果推送到数组中

您可以如下所示更改您的实现以解决上述问题:

const promiseAll = promises => {
    return new Promise((resolve, reject) => {
        if (promises.length === 0) {
          resolve([]);
          return;
        }

        const results = [];
        let resolved = 0;

        function collectResult(result, index) {
          results[index] = result;
          resolved += 1;
          if (resolved === promises.length) {
            resolve(results);
          }
        }

        promises.forEach((value, index) => {
          if (
            typeof value === 'object' &&
            'then' in value &&
            typeof value.then === 'function'
          ) {
            value.then(res => collectResult(res, index)).catch(reject);
          } else {
            Promise.resolve(value).then(res => collectResult(res, index));
          }
        });
    });
};

推荐阅读