簡體   English   中英

我的 Promise.all() 實現有什么問題?

[英]What is the problem with my implementation of 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));
  });
});

問題是什么?

您的實施存在兩個主要問題:

  1. forEach()方法中,您有一個檢查: promise instanceof Promise 如果這個檢查是假的,你打電話Promise.resolve()但是你也打電話 promise.then promise.then(...) ; 您可能打算在else塊中調用then()方法

  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));
          }
        });
    });
};

您正在使用 Promise.resolve(promise) 創建一個新的 Promise,但您不會更改原始的 Promise var。

if (!(promise instanceof Promise)) {
  promise = Promise.resolve(promise);
}

編輯:在@Ivan Kleshnin 評論之后是根據規范的並行解決方案

Promise.all = async function (array) {
    const results = [];

     parllalLoopFinish = () =>{
        return results.length === array.length;
    }

    return new Promise((resolve,reject) =>{
        for (let index = 0; index < array.length; index++) {
            const promise = array[index];
            if(promise instanceof Promise){
                promise.then((value)=>{
                    results[index]=value;
                    if(parllalLoopFinish()) {
                        resolve(results);
                      }
                }).catch(reject)
            }
            else{
                results[index]=promise;
            }
        }
        if(parllalLoopFinish()) {
            resolve(results);
          }
    });

  };
  
  
  const promise1 = Promise.resolve(3);
  const promise2 = 42;
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "foo");
  });
  
  Promise.all([promise1, promise2, promise3]).then((res) => console.log(res));

因為您試圖在 p2 上調用then() ,這是一個數字。

這是我實現Promise.all()的方式

編輯:舊的迭代解決方案

Promise.all = async function (array) {
  const results = [];
  for (let index = 0; index < array.length; index++) {
      try {
        const value = await Promise.resolve(array[index]);
        results.push(value);
      } catch (error) {
        return Promise.reject(error);
      }
  }
  return Promise.resolve(results);
};


const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "foo");
});

Promise.all([promise1, promise2, promise3]).then((res) => console.log(res)); 
// print [3, 42, 'foo']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM