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

Geo*_*off 139 javascript callstack exception-handling exception stack-trace

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

try {
  enterAwesomeMode();
  doRiskyStuff(); // might throw an exception
} catch (e) {
  leaveAwesomeMode();
  throw e;
}
doMoreStuff();
leaveAwesomeMode();
Run Code Online (Sandbox Code Playgroud)

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

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

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

感谢任何指针:)

Gle*_*ard 74

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

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

我不知道有任何解决方法.

我终于没有看到问题.在某些情况下,我确实看到异常默认情况下没有出现在错误控制台上,但是在开发版本中似乎已经修复了.

  • 此问题已被关闭。 (9认同)

Mik*_*tay 22

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

   throw new Error("message");

如果您像编写代码一样使用代码,则在重新抛出错误时不会更改堆栈属性.

  • 这不是真的(可能取决于平台).我正在使用的js引擎(Rhino)重置了throw语句中的堆栈,丢失了原始堆栈. (4认同)

Ofe*_*gev 6

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

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

  console.error(err.stack);
  throw err;
Run Code Online (Sandbox Code Playgroud)

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