【问题标题】:How can I rethrow an exception in Javascript, but preserve the stack?如何在 Javascript 中重新抛出异常,但保留堆栈?
【发布时间】:2011-04-13 15:36:51
【问题描述】:

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

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

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

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

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

感谢任何指点:)

【问题讨论】:

标签: javascript exception exception-handling stack-trace callstack


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    抛出新错误(“消息”);

    如果你按照你写的代码来使用,当你重新抛出错误时,堆栈属性将不会改变。

    【讨论】:

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

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

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

    我不知道任何解决方法。

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

    【讨论】:

    • 这个问题已经被关闭了。
    • Chrome 92 对我来说仍然是坏的。error.stack 反映了重新抛出的行号不是原始的
    猜你喜欢
    • 2011-07-12
    • 1970-01-01
    • 2021-03-02
    • 2017-05-02
    • 1970-01-01
    • 2011-05-20
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多