我相信有些同窗在面試的過程當中,面試官會問你可否簡單描述一下
Promise.all
的原理,小編我也是被問到,因而也在網上找了幾遍文章和例子,看完以後也是死恍然大悟,但願能幫到小夥伴們git
Promise.all 接收一個 promise 對象的數組做爲參數,當這個數組裏的全部 promise 對象所有變爲resolve或 有 reject 狀態出現的時候,它纔會去調用 .then 方法,它們是併發執行的github
一、Promise.all()方法將多個Promise實例包裝成一個Promise對象(p),接受一個數組(p1,p2,p3)做爲參數,數組中不必定須要都是Promise對象,可是必定具備Iterator接口,若是不是的話,就會調用Promise.resolve將其轉化爲Promise對象以後再進行處理。面試
二、使用Promise.all()生成的Promise對象(p)的狀態是由數組中的Promise對象(p1,p2,p3)決定的;數組
Promise.all()方法生成的Promise對象也會有一個catch方法來捕獲錯誤處理,可是若是數組中的Promise對象變成rejected狀態時,而且這個對象還定義了catch的方法,那麼rejected的對象會執行本身的catch方法,而且返回一個狀態爲fullfilled的Promise對象,Promise.all()生成的對象會接受這個Promise對象,不會返回rejected狀態promise
function PromiseAll(arr) {
//PromiseAll的返回值爲一個promise對象
return new Promise((resolve, reject) => {
//PromiseAll的入參必須是數組
if (!Array.isArray(arr)) {
return reject(new TypeError('arr must be an array.'));
}
let resArr = [];
for (let i in arr) {
(function(i) {
Promise.resolve(arr[i]).then(res => {
resArr.push(res);
//只有全部的都成功了,纔會返回resolve
if (i == arr.length - 1) {
return resolve(resArr);
}
}, err => {
// 只要出錯就拋出
return reject(err)
}).catch(err => {
console.log(err)
})
})(i)
}
})
}
//測試
const pro1 = new Promise((res,rej) => {
setTimeout(() => {
res('1')
},1000)
})
const pro2 = new Promise((res,rej) => {
setTimeout(() => {
res('2')
},2000)
})
const pro3 = new Promise((res,rej) => {
setTimeout(() => {
res('3')
},3000)
})
const proAll = PromiseAll([pro1,pro2,pro3])
.then(res =>
console.log(res) // 3秒以後打印 ["1", "2", "3"]
)
.catch((e) => {
console.log(e)
})
複製代碼
function PromiseAll(promiseArrs) {
return new Promise((resolve, reject) => { //返回一個新的Promise
let arr = []; //定義一個空數組存放結果
let i = 0;
function handleData(index, data) { //處理數據函數
arr[index] = data;
i++;
if (i === promiseArrs.length) { //當i等於傳遞的數組的長度時
resolve(arr); //執行resolve,並將結果放入
}
}
for (let i = 0; i < promiseArrs.length; i++) { //循環遍歷數組
promiseArrs[i].then((data) => {
handleData(i, data); //將結果和索引傳入handleData函數
}, reject)
}
})
}
// 測試
const pro1 = new Promise((res,rej) => {
setTimeout(() => {
res('1')
},1000)
})
const pro2 = new Promise((res,rej) => {
setTimeout(() => {
res('2')
},2000)
})
const pro3 = new Promise((res,rej) => {
setTimeout(() => {
res('3')
},3000)
})
const proAll = PromiseAll([pro1,pro2,pro3])
.then(res =>
console.log(res) // 3秒以後打印 ["1", "2", "3"]
)
.catch((e) => {
console.log(e)
})
複製代碼
function PromiseAll(promiseArray) {
return new Promise(function(resolve,reject){
//判斷參數類型
if(!Array.isArray(promiseArray)){
return reject(new TypeError('arguments muse be an array'))
}
var counter = 0,
promiseNum = promiseArray.length,
resolvedArray = new Array(promiseNum);
for(var i = 0; i < promiseNum; i++){
(function(i){
Promise.resolve(promiseArray[i]).then(function(value){
counter++;
resolvedArray[i] = value;
if(counter == promiseNum){
return resolve(resolvedArray)
}
},function(reason){
return reject(reason)
})
})(i)
}
})
}
// 測試
const pro1 = new Promise((res,rej) => {
setTimeout(() => {
res('1')
},1000)
})
const pro2 = new Promise((res,rej) => {
setTimeout(() => {
res('2')
},2000)
})
const pro3 = new Promise((res,rej) => {
setTimeout(() => {
res('3')
},3000)
})
const proAll = PromiseAll([pro1,pro2,pro3])
.then(res =>
console.log(res) // 3秒以後打印 ["1", "2", "3"]
)
.catch((e) => {
console.log(e)
})
複製代碼
無論版本如何變更,只要圍繞Promise.all幾個特色解讀就能夠併發
介紹下 Promise.all 使用、原理實現及錯誤處理
手動實現一個 Promise.all()
實現promise.all方法
函數