天天看點

面試官讓我手寫Promise.all

原生的Promise.all有什麼特點?

  1. 特點1:接收一個可疊代對象
  2. 特點2:傳入的資料中可以是普通資料,也可以是Promise對象
  3. 特點3:可疊代對象的promise是并行執行的
  4. 特點4:保持輸入數組的順序和輸出數組的順序一緻
  5. 特點5:傳入數組中隻要有一個reject,立即傳回reject
  6. 特點6:所有資料resolve之後傳回結果

實作Promise.all

1:函數傳回的是一個Promise對象

function myPromiseAll(iterable) {
    return new Promise((resolve,reject) => {
    })
}
複制代碼      

2:将可疊代對象轉換為一個數組

const promises = Array.from(iterable);
複制代碼      

3:并發執行每一個Promise

// 定義一個計數器用來判斷是否所有的promise執行完畢
let count = 0;
// 并發執行每一個promise
for (let i = 0; i < promises.length; i++) {
    Promise.resolve(promises[i]).then(res => {
        result[i] = res;
        count++;
        if (count === promises.length) {
            resolve(result);
        }
    }).catch(err => reject(err))
}
複制代碼      
第三步是實作Promise.all的核心,有幾點需要我們注意:
  1. 并不是push進result數組的,而是通過下标的方式進行存儲,這是因為我們為了保證輸出的順序,因為Promise對象執行的時間可能不同,push的話會破壞順序。
  2. 通過計數标志來判斷是否所有的promise對象都執行完畢了,因為在then中表示該promise對象已經執行完畢。

完整實作

function myPromiseAll(iterable) {
    return new Promise((resolve,reject) => {
        const promises = Array.from(iterable);
        // 定義Promise對象resolve的數組
        const result = [];
        // 定義一個計數器用來判斷是否所有的promise執行完畢
        let count = 0;
        // 并發執行每一個promise
        for (let i = 0; i < promises.length; i++) {
            Promise.resolve(promises[i]).then(res => {
                result[i] = res;
                count++;
                if (count === promises.length) {
                    resolve(result);
                }
            }).catch(err => reject(err))
        }
    })
}
複制代碼      

Promise.all的實作給我們什麼啟示

  • Promise.all傳回的是一個Promise對象
  • Promise.all接收的可疊代對象數組需要通過Array.from轉換為數組
  • Promise.all是并發執行的。
  • Promise.all中一個reject直接傳回reject的結果。

繼續閱讀