Promise catch:如何知道错误是来自 Promise 拒绝还是来自 then 语句

Héc*_*tor 1 javascript promise es6-promise

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

fetch(...)
.then((response) => {...})
.catch((error) => {...});
Run Code Online (Sandbox Code Playgroud)

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

像下面这样的东西会起作用:

let success = false;
fetch(...)
.then((response) => {success = true; ...})
.catch((error) => {if(success) ...});
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有更好或更本地化的方法来做到这一点。我也尝试过做类似的事情:

fetch(...)
.catch((promiseError) => {...});
.then((response) => {...})
.catch((thenError) => {...});
Run Code Online (Sandbox Code Playgroud)

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

哪一个是更好的方法?

T.J*_*der 5

then接受两个参数\xc2\xb9:一个在完成时调用的函数,另一个在拒绝时调用。所以你可以更早地处理最初的拒绝:

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

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

\n

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

\n

因此,在您关心的情况下,您可以更接近源头进行处理。

\n

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

\n
\n

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

\n
aPromise.then(onFulfilled).catch(onRejected);\n
Run Code Online (Sandbox Code Playgroud)\n

不同于

\n
aPromise.then(onFulfilled, onRejected);\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

\xc2\xb9 事实上,.catch(fn)只是.then(undefined, fn). :-)规格链接

\n