最近工作中使用到Promise的情况比较多,Promise.all方法也用的不少,下面来总结一下使用的几种情况
我们先来看一下promise.all对错误的处理
Promise.all([new Promise((resolve,reject)=>{ reject(666) })]).catch(err=>{ console.log(err); //666 })
我们可以看到:内部的promise触发了reject路线,而且并没有写catch,但是并没有报错,而是被外界promise.all的catch捕捉到了错误并打印出来,所以对于promise.all的catch,可以看作try,catch冒泡处理错误。
经测试,一个promise处理内部promise的catch并不行
明确上面内容后,我们可以把场景分为几种情况
1.错误的promise没catch,promise.all写catch,如下
const promiseOne = new Promise((resolve, reject) => { resolve(111) }) const promiseTwo = new Promise((resolve, reject) => { reject(222) }) const promiseThree = new Promise((resolve, reject) => { resolve(333) }) Promise.all([promiseOne, promiseTwo,promiseThree]).then(res=>{ console.log('res'); console.log(res); }).catch(err=>{ console.log('err');// err console.log(err); // 222 })
由打印内容可知:产生错误的那个promise并没有处理错误,但是promise.all捕捉到错误并进行处理
2.错误的promise catch,promise.all无catch,如下
const promiseOne = new Promise((resolve, reject) => { resolve(111) }).catch(err=>{ }) const promiseTwo = new Promise((resolve, reject) => { reject(222) }).catch(err => { return 666 }) const promiseThree = new Promise((resolve, reject) => { resolve(333) }).catch(err => { }) Promise.all([promiseOne, promiseTwo,promiseThree]).then(res=>{ console.log('res'); //res console.log(res); //[ 111, 666, 333 ] })
我们可以看到,promise.all传的多个promise中有执行reject的,但是promise.all依旧执行then,这是因为catch处理的终归是报错,内部promise被自己的catch拦截下来了,则promise.all检测不到错误自然会执行then,值得一提的是每个promise的最后一次then/catch可以看作其返回值(特别是用await 获取的时候需注意)
3.错误的promise 有catch,promise.all有catch,如下
const promiseOne = new Promise((resolve, reject) => { resolve(111) }).catch(err=>{ }) const promiseTwo = new Promise((resolve, reject) => { reject(222) }).catch(err => { }) const promiseThree = new Promise((resolve, reject) => { resolve(333) }).catch(err => { }) Promise.all([promiseOne, promiseTwo,promiseThree]).then(res=>{ console.log('res'); console.log(res); }).catch(err=>{ console.log('err'); console.log(err); //[ 111, undefined, 333 ] })
结果基本同上,注意此次代码promise的catch中没有返回值,所以promise.all获取了一个undefined
3.错误的promise 无catch,promise.all无catch,如下
const promiseOne = new Promise((resolve, reject) => { resolve(111) }) const promiseTwo = new Promise((resolve, reject) => { reject(222) }) const promiseThree = new Promise((resolve, reject) => { resolve(333) }) Promise.all([promiseOne, promiseTwo,promiseThree]).then(res=>{ console.log('res'); console.log(res); })
不出所料,代码执行后报错如下
总结:若想要每个传入的promise都返回值,不管是否报错,则需要每个promise都单独写好自己的catch,若只想筛取执行成功的promise,可以参考如下
const promiseOne = new Promise((resolve, reject) => { resolve(111) }).catch(err=>{}) const promiseTwo = new Promise((resolve, reject) => { reject(222) }).catch(err=>{}) const promiseThree = new Promise((resolve, reject) => { resolve(333) }).catch(err=>{}) Promise.all([promiseOne, promiseTwo,promiseThree]).then(res=>{ console.log(Array.prototype.filter.call(res,Boolean)); //[ 111, 333 ] })
使用Array.prototype.filter.call是因为res可能为类数组
除此之外,也可以使用promise的另一个方法:Promise.allSettled , 如下
const promiseOne = new Promise((resolve, reject) => { resolve(111) }) const promiseTwo = new Promise((resolve, reject) => { reject(222) }) const promiseThree = new Promise((resolve, reject) => { resolve(333) }) Promise.allSettled ([promiseOne, promiseTwo,promiseThree]).then(res=>{ console.log(Array.prototype.filter.call(res,Boolean)); return Array.prototype.filter.call(res,Boolean) }) //[ // { status: 'fulfilled', value: 111 }, // { status: 'fulfilled', value: undefined }, // { status: 'fulfilled', value: 333 } //]
可以看到:不管出错的promise是否有自己的catch,Promise.allSettled都会返回对应截取值