如何在 Javascript 中重新抛出异常,但保留堆栈?
在Javascript中,假设我想在异常发生时执行一些清理,但让异常继续在堆栈中传播,例如:
try {
enterAwesomeMode();
doRiskyStuff(); // might throw an exception
} catch (e) {
leaveAwesomeMode();
throw e;
}
doMoreStuff();
leaveAwesomeMode();
这段代码的问题是捕获并重新抛出异常会导致堆栈跟踪信息到该点丢失,这样,如果随后再次捕获异常(在堆栈的较高位置),堆栈跟踪只会下降到重新抛出。这很糟糕,因为这意味着它不包含实际引发异常的函数。
事实证明, try..finally 至少在 Chrome 中具有相同的行为(也就是说,问题不在于重新抛出,而在于任何异常处理程序块的存在。)
有谁知道有没有一种方法可以在 Javascript 中重新抛出异常,但保留与其关联的堆栈跟踪?如果做不到这一点,是否可以建议其他方法来添加异常安全的清理处理程序,同时在异常发生时捕获完整的堆栈跟踪?
感谢您的指点:)
In Javascript, suppose I want to perform some cleanup when an exception happens, but let the exception continue to propagate up the stack, eg:
try {
enterAwesomeMode();
doRiskyStuff(); // might throw an exception
} catch (e) {
leaveAwesomeMode();
throw e;
}
doMoreStuff();
leaveAwesomeMode();
The problem with this code is that catching and rethrowing the exception causes the stack trace information up to that point to be lost, so that if the exception is subsequently caught again, higher up on the stack, the stack trace only goes down to the re-throw. This sucks because it means it doesn't contain the function that actually threw the exception.
As it turns out, try..finally has the same behavior, in at least Chrome (that is, it is not the re-throw that is the problem precisely, but the presence of any exception handler block at all.)
Does anyone know of a way to rethrow an exception in Javascript but preserve the stack trace associated with it? Failing that, how about suggestions for other ways to add exception-safe cleanup handlers, while also capturing complete stack traces when an exception happens?
Thanks for any pointers :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是 Chrome 中的一个错误。重新抛出异常应该保留调用跟踪。
http://code.google.com/p/chromium/issues/detail?id=60240< /a>
我不知道有什么解决方法。
我没有看到最终的问题。在某些情况下,我确实看到异常在finally之后没有默默地出现在错误控制台上,但这个问题似乎在开发版本中得到了修复。
This is a bug in Chrome. Rethrowing an exception should preserve the call trace.
http://code.google.com/p/chromium/issues/detail?id=60240
I don't know of any workaround.
I don't see the problem with finally. I do see exceptions silently not showing up on the error console in some cases after a finally, but that one seems to be fixed in development builds.
Error 对象的 stack 属性与 Error 对象本身同时创建,而不是在抛出错误时创建。由于习惯用法,它们通常是相同的
,如果您按照编写的方式使用代码,那么当您重新抛出错误时,堆栈属性将不会发生变化。
The stack property of an Error object is created at the same time as the Error object itself, not at the point it's thrown. They're often the same because of the idiom
and if you use the code just as you've written it, the stack property will not be changed when you rethrow the error.
如前所述,堆栈是运行
new Error(...)
时创建的快照,因此您不能真正使用相同的堆栈抛出错误。我使用的解决方法是在抛出之前
console.error
堆栈:它并不完美,但它可以为您提供足够的可调试信息以及原始错误的堆栈。
As mentioned, the stack is a snapshot created while running
new Error(...)
, so you can't really throw the error with the same stack.A workaround I used is to
console.error
the stack before throwing:It's not perfect, but it gets you enough debug-able information, and the stack of the original error.
我通常会创建自己的自定义错误类来执行此操作,并且无论我走到哪里都会随身携带它。它最终很有用,我在这些天构建的几乎每个应用程序中都使用它:
注意:这保留了原始的错误消息/堆栈。
您可以像这样抛出原始错误/堆栈:
您还可以检查此错误并以不同的方式处理它:
I usually create my own custom error class for doing this and have just brought it around with me wherever I go. It ends up being useful and I use this in almost every app I build these days:
NOTE: this preserves the original error message/stack.
You can throw the original error/stack like this:
You can also check for this error and handle it differently:
一开始就不要catch,直接使用finally
Don't catch it in the first place, just use finally