美文网首页
Promise.all()异常处理

Promise.all()异常处理

作者: 稚儿擎瓜_细犬逐蝶 | 来源:发表于2019-12-31 16:25 被阅读0次

    背景:

    promise.all中任何一个promise 出现错误的时候都会执行reject,导致其它正常返回的数据也无法使用。


    解决办法:

    • 切入点 1:
      由于Promise.all(request).then(…).catch(…) 会在所有requestresolve时才会进then方法,并且把所
      有结果以一个数组返回,只要有一个失败,就会进catch。而如果在单个请求中定义了catch方法,那么就
      不会进Promise.allcatch方法。因此,可以在单个的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 还是 rejectPromise.allSettled 都会执行 then 方法的第一个回调函数(意思就是不会 catch 到参数实例的 reject 状态),其回调函数的参数返回的数组的每一项是一个包含 statusvalue 或者 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"}
      ]*/
    })
    

    暂时只找到三种解决方案,如有补充,后续更新.

    相关文章

      网友评论

          本文标题:Promise.all()异常处理

          本文链接:https://www.haomeiwen.com/subject/gkucuctx.html