Promise.all:
function isPromise(obj) {
if (!!obj && (typeof(obj) === 'object' || typeof(obj) === 'function') && typeof(obj.then) === 'function') {
return true
} else {
return false
}
}
function newPromiseAll(arr) {
let result = [];
return new Promise( (resolve,reject) => {
for(let i = 0; i < arr.length; i++){
if(isPromise(arr[i])){
arr[i].then(data => {
result[i] = data;
if(result.length === arr.length) {
resolve(result)
}
}, reject)
} else {
result[i] = arr[i];
}
}
})
}
首先可以看到 Promise.all 返回了一个 Promise 对象。
Promise.all 是所有的 promise 都执行成功才执行resolve(当 result 的长度和数组长度一致时,resolve)有一个报错,就不执行。
那假如要改成,就算有一个报错,也能执行其他的 resolve。要怎么改呢?
function isPromise(obj) {
if (!!obj && (typeof(obj) === 'object' || typeof(obj) === 'function') && typeof(obj.then) === 'function') {
return true
} else {
return false
}
}
function newPromiseAll(arr) {
let result = [];
return new Promise( (resolve,reject) => {
for(let i = 0; i < arr.length; i++){
if(isPromise(arr[i])){
arr[i].then(data => {
result[i] = data;
if(result.length === arr.length) {
resolve(result)
}
}).catch (err => {
result[i] = err;
if(result.length === arr.length) {
resolve(result)
}
})
} else {
result[i] = arr[i];
}
}
})
}
首先将.then 里的第二个参数 reject去掉,这时当arr[i]报错时,就不会立即执行 reject然后执行最外层 Promise的 reject。
然后我们给.then 后面加上.catch,当 arr[i]执行失败时,会执行.catch 里的函数。然后我们在.catch 里将执行失败的结果也推进 result 里。
注意!!由于 arr[i]执行失败后执行了.catch,因此.catch 执行完后返回了一个新的Promise,且状态是 resolve!!所以他不会触发最外层的 Promise的 reject 了。
测试代码:
let p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
let p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
let p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
let p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
let p5 = new Promise((resolve, reject) => {
reject('reject');
});
newPromiseAll([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});