原生的Promise.all有什麼特點?
- 特點1:接收一個可疊代對象
- 特點2:傳入的資料中可以是普通資料,也可以是Promise對象
- 特點3:可疊代對象的promise是并行執行的
- 特點4:保持輸入數組的順序和輸出數組的順序一緻
- 特點5:傳入數組中隻要有一個reject,立即傳回reject
- 特點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的核心,有幾點需要我們注意:
- 并不是push進result數組的,而是通過下标的方式進行存儲,這是因為我們為了保證輸出的順序,因為Promise對象執行的時間可能不同,push的話會破壞順序。
- 通過計數标志來判斷是否所有的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的結果。