【问题标题】:Can't catch error thrown in promise using promises 'catch' [duplicate]使用承诺'catch'无法捕捉承诺中引发的错误[重复]
【发布时间】:2020-06-23 22:46:59
【问题描述】:

我有这个代码。

new Promise(() => {
  setTimeout(() => { throw new Error('ERROR') }, 1000);
}).catch(err => {
  console.log('CATCHED ', err);
});

并且它不会捕获错误,在 setTimeout 中抛出。 为什么?

【问题讨论】:

  • 这能回答你的问题吗? Handle error from setTimeout
  • @tmdesign 没有。在您提供的情况下,setTimeout 回调在 try-catch 块之后执行,我理解。在我的情况下,catch 块将等待 promise 被拒绝。

标签: javascript error-handling promise


【解决方案1】:

您对我的评论的评论表明该案例与其他答案不同。我真的无法在评论中加入这个解释,所以:

catch 块实际上不会等待 promise 被拒绝。试试这个:

const myPromise = new Promise(() => {
  console.log('inside of the promise');
  setTimeout(() => { console.log('inside of the timeout function'); throw new Error('ERROR') }, 1000);
}).catch(err => {
  console.log('CATCHED ', err);
});
console.log('outside of the catch block, and my promise is', myPromise);

你会发现catch消息的外部是在timeout函数内部的消息之前写入控制台的。此时,承诺尚未解决(待处理)。

当您使用 setTimeout 时,该函数将被添加到 JavaScript 队列的末尾。

编辑

你可以通过在 promise 上调用 reject 来解决这个问题。

const myPromise = new Promise((resolve,reject) => {
  setTimeout(() => { reject('ERROR'); }, 1000);
}).catch(err => {
  console.log('CAUGHT ', err);
});

这是不同的,因为在这种情况下拒绝函数被保存在一个范围气泡(闭包)中,所以它仍然能够解决。

编辑 2

我确实发现了另一个在 cmets 中有一些讨论的问题:

JavaScript Promises - reject vs. throw

据此,我将修改我的解释。

首先,将 catch blocks 与链接到 promise 的 catch function 分开是很有帮助的。将 Promise 视为使用内置的不可见 catch block 捕获抛出的错误。在处理它时,promise 的 catch block 将调用 'reject',这将触发 catch function

抛出的错误 => promise 的不可见(隐式)catch 块 => reject() => promise 的 catch() 函数

但是,如果错误是从不同的调用堆栈抛出的,它无法捕获它,它与 setTimeout 一起使用。

抛出错误(在来自 setTimeout 的另一个调用堆栈中)=> 未捕获的异常

链停在那里,因为异常在不同的调用堆栈中冒泡。

但是你仍然可以调用reject,触发catch函数,这就是上面的sn-p代码所做的。

reject => promise 的 catch() 函数

这是一个较短的事件链,直接切入您想要的行为——在 catch 函数中触发代码。

【讨论】:

  • 如果我这样做,为什么 catch 块等待超时回调? setTimeout(() => reject(new Error('ERROR')), 1000);
  • 我实际上正要建议你这样做。您需要在函数参数中包含解析/拒绝,我将编辑答案。
  • "这是不同的,因为在这种情况下,拒绝函数被保存在范围气泡(闭包)中,因此它仍然能够解决。"就是这样,现在很清楚了。万分感谢! :)
  • 没问题。我只想说,这是我的理解,也是我在其他地方看到的,但我愿意接受更好的解释。不过,代码已经过测试并且确实可以正常工作。
  • 请参阅我的答案中的编辑 2 以获得更好的解释。
猜你喜欢
  • 1970-01-01
  • 2017-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-28
  • 2016-03-10
  • 1970-01-01
相关资源
最近更新 更多