想象一个函数返回一个promise(例如从fetch获取API(:
fetch(...)
.then((response) => {...})
.catch((error) => {...});
我如何知道catch
语句中的错误是否是由于承诺拒绝而不是then
语句中的代码引起的?
以下内容将起作用:
let success = false;
fetch(...)
.then((response) => {success = true; ...})
.catch((error) => {if(success) ...});
但我想知道是否有更好或更本土的方法来做这件事。我也尝试过做一些类似的事情:
fetch(...)
.catch((promiseError) => {...});
.then((response) => {...})
.catch((thenError) => {...});
但我认为它不起作用,因为response
没有转发到then
语句(或者至少TS是这么说的(。
哪种方式更好?
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
调用中(被调用,用于由之前的处理程序的错误(或被拒绝的承诺(引起的拒绝(履行或拒绝(;如果原始promise被拒绝,它不会被调用(但如果第一个拒绝处理程序抛出错误或返回被拒绝的promise,它很可能会被调用(。
因此,在那些你关心的情况下,你可以更接近源头地处理它。
请注意所有没有抛出错误或返回被拒绝/将被拒绝的承诺的拒绝处理程序都会将拒绝(原始承诺(转换为实现(then
/catch
中的承诺(。这可能对下游then
处理程序很重要。
理解这一点的关键是记住then
(及其包装catch
和finally
(返回一个新的promise。这就是为什么:
aPromise.then(onFulfilled).catch(onRejected);
与不同
aPromise.then(onFulfilled, onRejected);
第一个将履行处理程序挂接到aPromise
,然后将拒绝处理程序挂接到承诺then
返回(这意味着如果aPromise
拒绝,则调用拒绝处理程序;如果履行处理程序抛出错误或返回拒绝的承诺,则调用(。相反,第二个只挂接aPromise
上的处理程序,因此来自履行处理程序的错误/拒绝不会触发拒绝处理程序。
事实上,.catch(fn)
只是.then(undefined, fn)
的包装器。:-(规范链接
如果传递给then
的函数返回promise,
promise
.then(
(async (response)=>{
...
}).catch((errorFromThen) => {})
).catch((errorFromPromise) => {})
或者仅仅是
promise
.then(
(response)=>{
try {
...
} catch (errorFromThen) {
...
}
}
).catch((errorFromPromise) => {})