背景:
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"}
]*/
})
暂时只找到三种解决方案,如有补充,后续更新.