JavaScript错误处理的最佳实践是什么?


137

我期待开始做我的JavaScript多一点错误的证明,而且我发现很多文档的使用trycatchfinally,和throw,但我不是专家在何时何地抛出错误找一吨的建议。

  • 是否应该将每段代码都包裹在try / catch中?
  • 有没有想更多的意见本上在什么点错误应该被抓?
  • 产生错误而不是使代码在生产中静默失败是否有缺点?
  • SO在实现方面已经涉及到这一点,但是服务器记录JS错误是否是有效的策略?
  • 关于捕获应用程序中的错误,我应该知道的其他什么?

我也完全可以聆听游戏中的书籍,这些书籍包含出色的章节或对错误处理的深入说明。雄辩的JavaScript触及了这个问题,但对这个问题的描述或看法不是很明确。

感谢您提供的任何建议!


当然,这取决于出现问题时失败的严重程度以及可能的错误消息数量。您不希望因为错误日志目录已满而失败吗?-没看过吗?stackoverflow.com/search?q=error+logging+javascript
mplungjan 2011年

@mplungjan-我确实浏览了那里的答案,但似乎并没有太多意义,并且搜索Javascript错误处理/异常最佳实践并没有发现任何问题,因此,我认为尝试提出一些简洁的想法可能会有所帮助,这对我来说都是自己的理解和将来的搜索者。也许这是一个不可能制定最佳实践的话题,但是每种情况都是非常独特的?
约书亚·科迪,

1
“是否应该将每段代码都包含在try / catch中?” 当然不是。您知道有很多代码将一直有效(当然,假设您对其进行了测试,但是try / catch的目的不是捕获或掩盖编码错误)。只包装可能在某些时候由于其控制范围之外的东西而失败的代码,通常是诸如资源访问之类的东西。注意:某些可能失败的东西具有内置的错误处理,例如,当出现以下情况时,我不会从头开始编写Ajax代码有很多可以处理跨浏览器问题并允许您指定错误处理程序功能的库。
nnnnnn

1
乔什(+1)是个好问题。周围有很多句法建议,但是就像您说的那样,这很容易。该问题的答案(stackoverflow.com/questions/2825427/…)涉及到该内容,其中解释了JS中不普遍使用异常,并给出了原因。
whitneyland 2011年

Answers:


63

可以在http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/上找到有关企业JavaScript错误处理的一组非常有趣的幻灯片

简而言之,它总结:

  1. 假设您的代码将失败
  2. 将错误记录到服务器
  3. 您(而不是浏览器)处理错误
  4. 确定可能发生错误的地方
  5. 抛出自己的错误
  6. 区分致命错误与非致命错误
  7. 提供调试模式

幻灯片会更加详细,并且很可能会为您提供一些指导。

更新

上面提到的演示文稿可以在这里找到:http : //www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation


24
devhands链接已损坏。
瑞恩·盖茨

7
对于2017年阅读此书的人,我认为您不会从幻灯片中获得太多价值-此摘要为您提供了90%的信息。它仍然是有价值的信息。干杯!
菲利普·赫伯特

29

雅虎的尼古拉斯·扎卡斯(Nicholas Zakas)!名声在Ajax Experience 2008 上进行了有关企业错误处理的演讲(幻灯片),他提出了类似的建议:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

一年后,尼古拉斯·扎卡斯(Nicholas Zakas)在他的博客上发布了一个更新,其中包括一个巧妙的模式,可以在生产环境中自动注入错误处理代码(使用面向方面的编程)。

当您开始记录window.error调用时,您将注意到两件事:

  1. 如果您的网站相当复杂,则会记录很多错误
  2. 您将看到一堆无用的“ window.error in undefined:0”消息

减少日志条目的洪流就像在登录服务器之前测试严重性和/或随机数一样简单:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

处理无用的“ undefined:0中的window.error”错误取决于您的站点体系结构,但是可以尝试识别所有Ajax调用并在出现故障时引发异常(可能使用stacktrace.js返回堆栈跟踪)。


67
我知道这是一个老问题,但是建议随机忽略一些错误是我听过的最糟糕的想法之一。
jbabey 2013年

26
@jbabey:对于小型站点来说是正确的,但是如果您正在运行一个拥有100,000s或数百万用户的大型站点,则实际上并不需要向服务器(或Internet)发送过多的日志记录请求。在足够大的系统上,每个实际错误每天都会发生成千上万次,因此这种限制形式可以正常工作。这个想法实际上是在Facebook上实现的。
詹斯·罗兰

1
在调试模式下记录错误可能与限制生产错误报告同样重要,因此可能有人注意到,需要一种解决方案来管理限制记录阈值的值。
frattaro 2015年

2
@NickBull我在2011-2012年间反向设计了许多Facebook JavaScript模块;那是我找到它的地方。
延斯·罗兰

1
@NickBull只是检查了我的旧文件,仍然有这些文件。我在Facebook引导程序模块中找到了这个技巧:(if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {诚然,该代码并不能限制所有错误,仅限制特定类别的超时错误)
Jens Roland

7

IHMO,您应该像其他几种语言(AFAIK:Python,Java)一样在javascript中使用错误处理。

为了获得更好的可读性(即使我不确定它是否会产生很大的影响,也可能会有更好的性能),您应该在以下情况下主要使用try / catch块:

  • 您要包装的代码部分是整个算法的关键部分。如果失败,则可能:

    • 在代码的下一部分上创建错误(例如,因为缺少var ...)
    • 使页面看起来不像预期的那样(对内容或CSS的影响)
    • 使结果对用户看起来很奇怪(影响代码行为)
  • 您知道您正在编写的代码与每个浏览器都不兼容

  • 您计划代码可能会失败(因为没有其他方法可以通过... then ...块检查它是否可以正常工作)
  • 而且,当您想调试而又不打扰最终用户时

最终,JavaScript专家可能还会提供其他元素。

我的2美分到盒子里

问候,

最高


1
“您要包装的代码部分是整个算法的关键部分”-可能取决于您要如何处理故障。如果您知道无法在失败时继续执行算法,则最好将整个内容包装在try / catch中,因为如果您的try / catch被(例如)埋在嵌套循环中,那将对性能造成更大的影响。另一方面,如果您可以对异常采取一些措施并继续执行算法,那么您将需要更细粒度的try / catch设置。
nnnnnn

5

除其他答案外:重要的一点是使用 JavaScript错误对象和window.onerror函数参数中可用的上下文数据

诸如stacktrace(errorObject.stack),文件名,行号和列号之类的东西。请注意,每个浏览器都有一些差异...因此,请尽最大努力获取正确的错误。

控制台对象本身甚至可能存在问题。我使用一个受此启发的自定义window.onerror函数和一个特殊函数来跟踪受此代码启发的任何给定的标准错误对象。

另一个好处是将Web应用程序的版本包括在靠近stacktrace的位置(以便快速,安全地进行复制和粘贴)。在开发模式下,由于开发人员将不会持续监视浏览器控制台并且可能看不到某些问题,因此您也可能会更主动地显示错误(警告...)。

也可以使用避免使用throw 'My message',使用throw new Error('My message'),甚至可以自定义错误,请阅读本文

始终在错误中添加一些上下文(版本,对象的ID,一些自定义消息等),并确保区分外部错误(某些外部数据或情况导致系统发生故障)和内部错误/ assertions(您自己的系统搞砸了),请阅读有关“ 按合同设计 ”的信息。

这是一个指南

还要考虑使用一般的错误处理,例如拦截器的库和框架:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.