promise catch:如何知道错误是来自 promise 拒绝还是来自 then 语句
promise catch: how to know if the error comes from promise rejection or from the then statement
想象一个 returns 承诺的函数(例如从 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
没有转发到 then
声明(或者至少 TS 是这么说的)。
哪种方法更好?
如果函数传递给 then
returns 一个承诺,
promise
.then(
(async (response)=>{
...
}).catch((errorFromThen) => {})
).catch((errorFromPromise) => {})
或者只是简单地
promise
.then(
(response)=>{
try {
...
} catch (errorFromThen) {
...
}
}
).catch((errorFromPromise) => {})
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
调用中)被调用以处理由它之前的处理程序(实现或拒绝)的错误(或拒绝的承诺)引起的拒绝;如果原始承诺被拒绝,它不会被调用(但如果第一个拒绝处理程序抛出错误或 return 承诺 is/will 被拒绝,它可能会被调用)。
所以在那些你关心的情况下,你可以更接近源地处理它。
注意所有不抛出错误或return承诺is/will被拒绝的拒绝处理程序转换拒绝(原始的承诺)转化为实现(来自 then
/catch
的)。这对下游 then
处理程序很重要。
理解这一点的关键是要记住 then
(及其包装器 catch
和 finally
)return 一个新的承诺。这就是为什么:
aPromise.then(onFulfilled).catch(onRejected);
与
不同
aPromise.then(onFulfilled, onRejected);
第一个将履行处理程序连接到 aPromise
,然后将拒绝处理程序连接到承诺 then
returns(这意味着拒绝处理程序将被调用如果 aPromise
拒绝 或 如果履行处理程序抛出错误或 return 拒绝承诺)。相反,第二个仅在 aPromise
上挂接处理程序,因此来自履行处理程序的 errors/rejections 不会触发拒绝处理程序。
¹ 事实上,.catch(fn)
只是 .then(undefined, fn)
的包装。 :-) spec link
想象一个 returns 承诺的函数(例如从 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
没有转发到 then
声明(或者至少 TS 是这么说的)。
哪种方法更好?
如果函数传递给 then
returns 一个承诺,
promise
.then(
(async (response)=>{
...
}).catch((errorFromThen) => {})
).catch((errorFromPromise) => {})
或者只是简单地
promise
.then(
(response)=>{
try {
...
} catch (errorFromThen) {
...
}
}
).catch((errorFromPromise) => {})
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
调用中)被调用以处理由它之前的处理程序(实现或拒绝)的错误(或拒绝的承诺)引起的拒绝;如果原始承诺被拒绝,它不会被调用(但如果第一个拒绝处理程序抛出错误或 return 承诺 is/will 被拒绝,它可能会被调用)。
所以在那些你关心的情况下,你可以更接近源地处理它。
注意所有不抛出错误或return承诺is/will被拒绝的拒绝处理程序转换拒绝(原始的承诺)转化为实现(来自 then
/catch
的)。这对下游 then
处理程序很重要。
理解这一点的关键是要记住 then
(及其包装器 catch
和 finally
)return 一个新的承诺。这就是为什么:
aPromise.then(onFulfilled).catch(onRejected);
与
不同aPromise.then(onFulfilled, onRejected);
第一个将履行处理程序连接到 aPromise
,然后将拒绝处理程序连接到承诺 then
returns(这意味着拒绝处理程序将被调用如果 aPromise
拒绝 或 如果履行处理程序抛出错误或 return 拒绝承诺)。相反,第二个仅在 aPromise
上挂接处理程序,因此来自履行处理程序的 errors/rejections 不会触发拒绝处理程序。
¹ 事实上,.catch(fn)
只是 .then(undefined, fn)
的包装。 :-) spec link