我在处理 JavaScript 中的错误方面拥有丰富的经验。我主要使用 Chrome 来建立我的理解,但其中大部分也适用于 Firefox 和 Internet Explorer。
我可以立即揭穿你关于静默 JavaScript 错误的假设。它们不存在,错误总是出现。Firefox 或 Chrome 的 webdev 中可能存在错误,但错误仍然存在。
不出现错误的最常见方法是您自己发现了它们。也许为时过早。
我已经想出了我认为捕获错误的最佳策略:
1. 总是扔掉Error
s 或继承自Error
s 的东西。
例如:不是:throw "Precondition failed"
但是throw new Error("Precondition failed")
。
这是因为错误在 JavaScript 中很奇怪(我没有别的词)。如果你想要一个堆栈跟踪(天堂是的,你想要一个堆栈跟踪),你需要抛出一个Error
(而不是字符串)。
2.不要使用window.onerror这里不多说。没用的。您无法控制向此函数发送的内容。它可能是您的代码,也可能是访问者使用的损坏插件。此外,没有堆栈跟踪。
3. 拥有一个(全局)错误处理程序/何时捕获错误
JavaScript 是事件驱动的。这会产生一些意想不到的后果。观察以下代码:
try {
setTimeout(function () {
throw new Error("nope! :D");
}, 1);
} catch (e) {
console.log(e);
}
您不会看到此错误。(萤火虫/控制台会捕捉到它)
这是因为内部函数在它自己的事件中运行,而 try-catch 语句不再适用于它。正确的方法是:
try {
setTimeout(function () {
try {
throw new Error("nope! :D");
} catch (e) {
console.log("Hell yea!", e);
}
}, 1);
} catch (e) {
console.log(e);
}
或者只是制作一个将函数包装在 try-catch 中的函数:
function wrap(wrap_dat_func) {
return function () {
try {
wrap_dat_func.apply(wrap_dat_func, arguments);
} catch (e) {
// send to error handler
}
}
}
像这样使用:
setTimeout(wrap(function () {
// etc
}), 1);
所以基本上每当你生成一个新事件时,将回调包装在你的全局 try catch 函数中。所以包装对所有与 DOM 相关的事件(如AJAX 调用)setTimeout
的调用。setInterval
onclick
onload
ondocumentready
onreadystatechanged
如何获得正确的堆栈跟踪(通过事件!)是另一个冗长的解释。