ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Javascript 中重新抛出异常,但保留堆栈?

在 Javascript 中,假设我想在发生异常时执行一些清理,但让异常继续向上传播堆栈,例如:

try {
  enterAwesomeMode();
  doRiskyStuff(); // might throw an exception
} catch (e) {
  leaveAwesomeMode();
  throw e;
}
doMoreStuff();
leaveAwesomeMode();

这段代码的问题是捕获并重新抛出异常会导致到该点的堆栈跟踪信息丢失,因此如果随后再次捕获异常,堆栈上的更高位置,堆栈跟踪只会下降到重新-扔。这很糟糕,因为这意味着它不包含实际引发异常的函数。

事实证明,try..finally 至少在 Chrome 中具有相同的行为(也就是说,问题并不是重新抛出,而是任何异常处理程序块的存在。)

有谁知道在 Javascript 中重新抛出异常但保留与之关联的堆栈跟踪的方法?如果做不到这一点,关于添加异常安全清理处理程序的其他方法的建议如何,同时在异常发生时捕获完整的堆栈跟踪?

感谢您的任何指点:)


G
Glenn Maynard

这是 Chrome 中的一个错误。重新抛出异常应该保留调用跟踪。

http://code.google.com/p/chromium/issues/detail?id=60240

我不知道任何解决方法。

我看不到最后的问题。在某些情况下,我确实看到异常在 finally 之后没有出现在错误控制台上,但似乎在开发版本中已修复。


此问题已被关闭。
从 Chrome 92 开始对我来说仍然是坏的。error.stack 反映了重新抛出的行数不是原始的
j
jpaugh

Error 对象的 stack 属性与 Error 对象本身同时创建,而不是在它被抛出时创建。由于成语,它们通常是相同的

throw new Error("message");

如果您按照编写的代码使用代码,则在重新抛出错误时不会更改堆栈属性。


这不是真的(可能取决于平台)。我现在使用的 js 引擎(Rhino)在 throw 语句上重置堆栈,丢失原始堆栈。
也许是这样,但 rhino-1.7.7.2.jar 并没有改变它。你用的是什么版本?
O
Ofer Segev

如前所述,堆栈是在运行 new Error(...) 时创建的快照,因此您不能真正使用同一个堆栈引发错误。

我使用的解决方法是在抛出之前 console.error 堆栈:

  console.error(err.stack);
  throw err;

它并不完美,但它为您提供了足够的可调试信息,以及原始错误的堆栈。


t
texuf

不要一开始就抓住它,只用finally

try {
  enterAwesomeMode();
  doRiskyStuff(); // might throw an exception
  doMoreStuff();
} finally {
  leaveAwesomeMode();
}