处理承诺中的错误时返回成功

时间:2018-10-16 08:27:39

标签: javascript typescript vue.js promise

我有一个承诺,可以处理通过Web API执行的HTTP请求:

promise = promise.then(r => { 
    // ...
  }, error => {
    if (error.status == 404) {
      // Here I can fix an error and continue properly
    } else {
      // Here the error should be propagated further in the promise
    }
}

// later in the code:
promise.catch(r => { /* More error handling */ } );

在代码中,此承诺链接到更多错误检查。

如果发生404错误,我实际上可以“解决”问题,并且我不希望其他处理程序触发。在这种情况下,我宁愿兑现诺言。我该怎么办?


更多代码可以更深入地解释我的情况:

refresh() {
  this.refreshAsync().catch(r => {
     // Show error to the user.
     notifications.showError("Unexpected error happened");
  });
}

async refreshAsync() {
  // Here goes a lot of vue-resource calls to gather the necessary data for a view. They are chained with `await`. Only one of them:
  await this.$http.get(url).then(r => {
    this.data = r.data;
  }, error => {
    // 404 is actually a legit response for API to return, so the user notification above should not be shown
    if (error.status == 404) {
      // handle successfully
    } else {
      // propagate an error, so the handler above could show a warning to the user.
    }

  });

}

3 个答案:

答案 0 :(得分:2)

您可以简单地返回拒绝/解决

if(error.status == 404)
    return Promise.resolve('OK')
else
    return Promise.reject('fail')

我举了一个例子说明如何工作, 仅在这种情况下:

httpRequest = function () {
  return new Promise(function (res, rej) {
    let status = (Math.round(Math.random()) === 1) ? 200 : 404;
    console.log(status)
    if (status === 200)
        return res({ status })
    else
        return rej({ status })
  })
}

let promise =
httpRequest()
    .then(res => Promise.resolve('success'))
    .catch(e => {
        if (e.status === 404)
            return Promise.resolve('success')
        else
            return Promise.reject('failed')
    })

promise
.then(res => {
    console.log(res)
})
.catch(e => {
    console.log('this should not happen')
})

答案 1 :(得分:1)

如果您在“修复”成功流程时需要传播成功流程,我可以在这里想到两种方法,

  1. 您可以将进一步的传播逻辑包装在一个函数中,然后在错误情况下调用它。
  2. promise换成另一个Promise,并在错误404上调用resolve(yourValue)。但这意味着您将不得不在promise对象上更改进一步的链式逻辑,但在相反,这将为您提供更大的灵活性。

希望它会有所帮助;)

编辑

看到您的代码后,我仍然觉得可以通过前面提到的内容来实现。您可以--

refreshAsync = async () => {
   return new Promise((resolve,reject)=>{
       await this.$http.get(url).then(r => {
           this.data = r.data;
        }, error => {
            if (error.status == 404) {
                 resolve(); //populate this with your desired value
           } else {
                 reject();
           }
   })
}

答案 2 :(得分:1)

如果您使用的是standard Promise implementation,则只需抛出一个错误,然后它将作为失败的promise结果返回给下一个catch方法:

// let's assume we have the following async operation
const somePromiseCall = () =>
  new Promise(resolve => setTimeout(() => resolve(), 1000))

somePromiseCall()
  .then(() => {
    if (Math.random() > .5) {
      throw 'this is the error message'
    }

    return 'this is the result'
  })
  .then(result => console.log('success', result))
  .catch(err => console.error('fail', err))

另一种方法是通过返回另一个您可以立即拒绝的承诺(通过返回new Promise((resolve, reject)=>reject('error message'))或通过返回简写方法Promise.reject('error message')

// let's assume we have the following async operation
const somePromiseCall = () =>
  new Promise(resolve => setTimeout(() => resolve(), 1000))

somePromiseCall()
  .then(() => {
    if (Math.random() > .5) {
      return Promise.reject('error message')
    }

    return 'this is the result'
  })
  .then(result => console.log('success', result))
  .catch(err => console.error('fail', err))

第二个版本起作用的原因是,来自thencatch方法的任何返回值都包装在promise中并传递给您,以便您可以链接then调用。 知道这一点,如果您返回一个值,则then方法在幕后实际上会返回类似Promise.resolve(returnValue)的内容,以便您可以进行链接:

somePromiseCall()
  .then(result => result + 1)
  .then(newResult => /* newResult === result + 1 */) 

这就是上面的代码段与此类似的原因:

somePromiseCall()
  .then(result => Promise.resolve(result + 1))
  .then(newResult => /* newResult === result + 1 */) 

请记住,您还可以返回实际上可以使用catch方法捕获的被拒绝的诺言:

somePromiseCall()
  .then(result => Promise.reject('reason'))
  .catch(err => console.log('error', err))