背景:
promise.all中任何一个promise出现错误的时候都会执行reject,导致其它正常返回的数据也无法使用。
解决办法:
- 切入点 1:
由于Promise.all(request).then(…).catch(…)会在所有request都resolve时才会进then方法,并且把所
有结果以一个数组返回,只要有一个失败,就会进catch。而如果在单个请求中定义了catch方法,那么就
不会进Promise.all的catch方法。因此,可以在单个的catch中对失败的promise请求做处理,可以使
成功的请求正常返回。
function getData(api){
return new Promise((resolve,reject) => {
setTimeout(() => {
var ok = Math.random() > 0.5 // 模拟请求成功或失败
if(ok)
resolve('get ' + api + ' data')
else{
reject('error') // 正常的reject
}
},2000)
})
}
function getDatas(arr){
var promises = arr.map(item => getData(item))
return Promise.all(promises.map(p => p.catch(e => e))).then(values => { // 关键步骤,map(p => p.catch(e => e)) 在每个请求后加上 catch 捕获错误;
values.map((v,index) => {
if(v == 'error'){
console.log('第' + (index+1) + '个请求失败')
}else{
console.log(v)
}
})
}).catch(error => {
console.log(error)
})
}
getDatas(['./api1','./api2','./api3','./api4']).then(() => '请求结束')
- 切入点 2:
出现错误请求之后不进行reject操作,而是继续resolve('error), 之后同意交给promise.all()进行处理.
function getData(api){
return new Promise((resolve,reject) => {
setTimeout(() => {
var ok = Math.random() > 0.5 // 模拟请求成功或失败
if(ok)
resolve('get ' + api + ' data')
else{
// reject(api + ' fail') // 如果调用reject就会使Promise.all()进行失败回调
resolve('error') // Promise all的时候做判断 如果是error则说明这条请求失败
}
},2000)
})
}
function getDatas(arr){
var promises = arr.map(item => getData(item))
return Promise.all(promises).then(values => {
values.map((v,index) => {
if(v == 'error'){
console.log('第' + (index+1) + '个请求失败')
}else{
console.log(v)
}
})
}).catch(error => {
console.log(error)
})
}
getDatas(['./api1','./api2','./api3','./api4']).then(() => '请求结束')
- 切入点 3:
Primise.allSettled
注意:这个方法是
ES2020中的新特性,只适用于ES2020版本哦!
与 Promise.all 一样,参数是一组包含 Promise 实例的数组,返回值是一个新的 Promise 实例,其实例在调用 then 方法中的回调函数的参数仍是一个数组。不同之处在于无论参数实例 resolve 还是 reject , Promise.allSettled 都会执行 then 方法的第一个回调函数(意思就是不会 catch 到参数实例的 reject 状态),其回调函数的参数返回的数组的每一项是一个包含 status 和 value 或者 reason 的一组对象。 status 代表对应的参数实例状态值,取值只有 fulfilled(resolve状态) 和 rejected(reject状态) ,当 status 的值为 rejected ,对应的另一个对象属性就是 reason 了,也就是被 reject 的原因,而成功返回的 status 的值则是 fulfilled ,对应的另一个对象属性便是 value ,对应的值就是 resolve 的任意值。
var promise1 = new Promise(function(resolve,reject){
setTimeout(function(){
reject('promise1')
},2000)
})
var promise2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve('promise2')
},3000)
})
var promise3 = Promise.resolve('promise3')
var promise4 = Promise.reject('promise4')
Promise.allSettled([promise1,promise2,promise3,promise4]).then(function(args){
console.log(args);
/*
result:
[
{"status":"rejected","reason":"promise1"},
{"status":"fulfilled","value":"promise2"},
{"status":"fulfilled","value":"promise3"},
{"status":"rejected","reason":"promise4"}
]*/
})
暂时只找到三种解决方案,如有补充,后续更新.