【问题标题】:promise catch: how to know if the error comes from promise rejection or from the then statement承诺捕获:如何知道错误是来自承诺拒绝还是来自 then 语句
【发布时间】:2022-02-09 21:25:53
【问题描述】:

想象一个返回承诺的函数(例如从 fetch API 获取):

fetch(...)
.then((response) => {...})
.catch((error) => {...});

我如何知道catch 语句中的错误是否是由于promise 拒绝而不是then 语句中的代码引起的?

以下内容将起作用:

let success = false;
fetch(...)
.then((response) => {success = true; ...})
.catch((error) => {if(success) ...});

但我想知道是否有更好或更本土的方式来做到这一点。我也尝试过这样做:

fetch(...)
.catch((promiseError) => {...});
.then((response) => {...})
.catch((thenError) => {...});

但我认为它不起作用,因为 response 没有转发到 thenstatement(或者至少 TS 是这么说的)。

哪种方式更好?

【问题讨论】:

  • 您可以查看error.message 以确定是什么原因造成的。或者您可以使用 try catch 块并等待承诺,这样您就可以分别捕获错误。最佳方法取决于您的实际目标。
  • 处理此问题的一种方法是定义一个自定义错误类,并从then 方法的回调函数中抛出该自定义错误类的实例。在catch方法的回调函数中,你可以检查错误参数是否是你自定义错误类的实例。

标签: javascript promise es6-promise


【解决方案1】:

then 接受两个参数¹:一个调用执行的函数,另一个调用拒绝的函数。所以你可以更早地处理最初的拒绝:

fetch(/*...*/)
.then(
    // Fulfillment handler
    (response) => {
        /*...*/
    },
    // Rejection handler for `fetch` promise
    (error) => {
        /*...*/
    }
)
.catch((error) => {
    // This rejection handler only sees errors not handled above
});

第一个拒绝处理程序(在then 调用中)仅在来自fetch 的承诺被拒绝时调用,而不是由履行处理程序中的错误引起的拒绝。

第二个拒绝处理程序(在catch 调用中)被调用以处理由它之前的处理程序(履行或拒绝)的错误(或被拒绝的承诺)引起的拒绝;如果原始承诺被拒绝,它不会被调用(但如果第一个拒绝处理程序抛出错误或返回被/将被拒绝的承诺,它很可能会被调用)。

所以在你关心的那些情况下,你可以在更靠近源头的地方处理它。

注意,所有既不抛出错误也不返回被/将被拒绝的承诺的拒绝处理程序将拒绝(原始承诺)转换为履行(来自@987654327 @/catch)。这对下游 then 处理程序很重要。


理解这一点的关键是记住then(及其包装器catchfinally返回一个新的承诺。这就是为什么:

aPromise.then(onFulfilled).catch(onRejected);

不同
aPromise.then(onFulfilled, onRejected);

第一个将履行处理程序连接到aPromise,然后将拒绝处理程序连接到承诺then返回(这意味着如果aPromise拒绝 如果履行处理程序抛出错误或返回拒绝的承诺)。相反,第二个仅在aPromise 上挂接处理程序,因此来自履行处理程序的错误/拒绝不会触发拒绝处理程序。


¹ 事实上,.catch(fn) 只是.then(undefined, fn) 的包装。 :-) spec link

【讨论】:

    【解决方案2】:

    如果传递给then 的函数返回一个promise,

    promise
        .then(
            (async (response)=>{
                ...
            }).catch((errorFromThen) => {})
        ).catch((errorFromPromise) => {})
    

    或者干脆

    promise
        .then(
            (response)=>{
                try {
                    ...
                } catch (errorFromThen) {
                    ...
                }
            }
        ).catch((errorFromPromise) => {})
    

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 2014-08-10
      • 2017-10-25
      • 2018-05-09
      • 2018-02-19
      • 2018-02-23
      • 2022-11-11
      • 2019-01-08
      相关资源
      最近更新 更多