如何捕获和分析 JavaScript Error

标签: JavaScript | 发表时间:2014-09-17 21:59 | 作者:天涯孤雁
出处:http://www.blogread.cn/it/

标签:   Error

前端工程师都知道 JavaScript 有基本的异常处理能力。我们可以 throw new Error(),浏览器也会在我们调用 API 出错时抛出异常。但估计绝大多数前端工程师都没考虑过收集这些异常信息。反正只要 JavaScript 出错后刷新不复现,那用户就可以通过刷新解决问题,浏览器不会崩溃,当没有发生过好了。这种假设在 Single Page App 流行之前还是成立的。现在的 Single Page App 运行一段时间后状态复杂无比,用户可能进行了若干输入操作才来到这里的,说刷新就刷新啊?之前的操作岂不要完全重做?所以我们还是有必要捕获和分析这些异常信息的,然后我们就可以修改代码避免影响用户体验。

捕获异常的方式

我们自己写的 throw new Error() 想要捕获当然可以捕获,因为我们很清楚 throw 写在哪里了。但是调用浏览器 API 时发生的异常就不一定那么容易捕获了,有些 API 在标准里就写着会抛出异常,有些 API 只有个别浏览器因为实现差异或者有缺陷而抛出异常。对于前者我们还能通过 try-catch 捕获,对于后者我们必须监听全局的异常然后捕获。

try-catch

如果有些浏览器 API 是已知会抛出异常的,那我们就需要把调用放到 try-catch 里面,避免因为出错而导致整个程序进入非法状态。例如说 window.localStorage 就是这样的一个 API,在写入数据超过容量限制后就会 抛出异常,在 Safari 的隐私浏览模式下也会如此。

  
  1. try{

  2.  localStorage.setItem('date',Date.now());

  3. }catch(error){

  4.  reportError(error);

  5. }

另一个常见的 try-catch 适用场景是回调。因为回调函数的代码是我们不可控的,代码质量如何,会不会调用其它会抛出异常的 API,我们一概不知道。为了不要因为回调出错而导致调用回调后的其它代码无法执行,所以把调用回到放到 try-catch 里面是必须的。

  
  1. listeners.forEach(function(listener){

  2. try{

  3.    listener();

  4. }catch(error){

  5.    reportError(error);

  6. }

  7. });

window.onerror

对于 try-catch 覆盖不到的地方,如果出现异常就只能通过 window.onerror 来捕获了。

  
  1. window.onerror =

  2. function(errorMessage, scriptURI, lineNumber){

  3.    reportError({

  4.      message: errorMessage,

  5.      script: scriptURI,

  6.      line: lineNumber

  7. });

  8. }

注意不要耍小聪明使用 window.addEventListenerwindow.attachEvent 的形式去监听 window.onerror。很多浏览器只实现了 window.onerror,或者是只有 window.onerror 的实现是标准的。考虑到标准草案定义的也是 window.onerror,我们使用 window.onerror 就好了。

属性丢失

假设我们有一个 reportError 函数用来收集捕获到的异常,然后批量发送到服务器端存储以便查询分析,那么我们会想要收集哪些信息呢?比较有用的信息包括:错误类型( name)、错误消息( message)、脚本文件地址( script)、行号( line)、列号( column)、堆栈跟踪( stack)。如果一个异常是通过 try-catch 捕获到的,这些信息都在 Error 对象上(主流浏览器都支持),所以 reportError 也能收集到这些信息。但如果是通过 window.onerror 捕获到的,我们都知道这个事件函数只有 3 个参数,所以这 3 个参数以外的信息就丢失了。

序列化消息

如果 Error 对象是我们自己创建的话,那么 error.message 就是由我们控制的。基本上我们把什么放进 error.message 里面, window.onerror 的第一个参数( message)就会是什么。(浏览器其实会略作修改,例如加上 'Uncaught Error: ' 前缀。)因此我们可以把我们关注的属性序列化(例如 JSON.Stringify)后存放到 error.message 里面,然后在 window.onerror 读取出来反序列化就可以了。当然,这仅限于我们自己创建的 Error 对象。

第五个参数

浏览器厂商也知道大家在使用 window.onerror 时受到的限制,所以开始往 window.onerror 上面添加新的参数。考虑到只有行号没有列号好像不是很对称的样子,IE 首先把列号加上了,放在第四个参数。然而大家更关心的是能否拿到完整的堆栈,于是 Firefox 说不如把堆栈放在第五个参数吧。但 Chrome 说那还不如把整个 Error 对象放在第五个参数,大家想读取什么属性都可以了,包括自定义属性。结果由于 Chrome 动作比较快,在 Chrome 30 实现了新的 window.onerror 签名,导致 标准草案也就跟着这样写了。

  
  1. window.onerror =function(

  2.  errorMessage,

  3.  scriptURI,

  4.  lineNumber,

  5.  columnNumber,

  6.  error

  7. ){

  8. if(error){

  9.    reportError(error);

  10. }else{

  11.    reportError({

  12.      message: errorMessage,

  13.      script: scriptURI,

  14.      line: lineNumber,

  15.      column: columnNumber

  16. });

  17. }

  18. }

属性正规化

我们之前讨论到的 Error 对象属性,其名称都是基于 Chrome 命名方式的,然而不同浏览器对 Error 对象属性的命名方式各不相同,例如脚本文件地址在 Chrome 叫做

相关 [分析 javascript error] 推荐:

如何捕获和分析 JavaScript Error

- - IT技术博客大学习
标签:   Error. 前端工程师都知道 JavaScript 有基本的异常处理能力. 我们可以 throw new Error(),浏览器也会在我们调用 API 出错时抛出异常. 但估计绝大多数前端工程师都没考虑过收集这些异常信息. 反正只要 JavaScript 出错后刷新不复现,那用户就可以通过刷新解决问题,浏览器不会崩溃,当没有发生过好了.

Tomcat启动:A fatal error has been detected by the Java Runtime Environment(JVM Crash分析及相关资料)

- - CSDN博客推荐文章
2013年1月10号注:. 今天更新代码之后,突然出现一个问题:Tomcat启动时,总是会出现jvm fatal error错误导致tomcat无法正常启动,以下是错误信息:. 在网上搜寻好久,终于找到了类似错误,网上解释归结于:JIT在做编译优化的时候处理时出错,可能是触发了JVM的编译器的BUG导致的.

javascript 跨域请求详细分析

- - CSDN博客Web前端推荐文章
比如用户使用浏览器打开一个网站 (www.AAA.com)的首页,这个时候浏览器会执行来自网站www.AAA.com的一个javascript的函数,这个函数是向网站(www.BBB.com)请求数据: $.getJSON('www.BBB.com/index.php', funciton(data) {.

20個很有梗的「404 Error」網頁出錯頁面

- Alu - 大人物
對於從事網路業的人們來說,最害怕逛到的網頁不是整人網頁也不是色情網頁,而是令網路工程師們魂飛魄散的「404 Error」網頁出錯頁面,只要看到404頁面出現,就代表你的網站掛點,這時候可是想笑都笑不出來呢. 但是在叫天天不應、叫地地不靈的掛站摸門,你只能看著404網頁哭哭嗎. 以下這個20個超有梗的404 Error出錯網頁,反而會讓你更期待下一次的掛站呢XD.

Fatal Error log format,JVM 致命错误日志格式

- - 码蜂笔记
本文翻译自: http://www.oracle.com/technetwork/java/javase/felog-138657.html. 本文内容基于 Java SE 6,HotSpot JVM. 当一个致命错误发生时,一个错误日志将被创建,存储了在致命错误发生时获取到的信息和状态. 注意:这个文件的格式可能随着版本的更新而改变.

Java的Exception和Error面试题10问10答

- - ITeye博客
JAVA 中Exception和Error 面试问题.   下面是我个人总结的在Java和J2EE开发者在面试中经常被问到的有关Exception和Error的知识. 回答的时候,我也给这些问题作了快速修订,并且提供源码以便深入理解. 我总结了各种难度的问题,适合新手码. 如果你遇到了我列表中没有的问题,并且这个问题非常好,请在下面评论中分享出来.

Chrome开发者工具之JavaScript内存分析

- - 极客521 | 极客521
内存泄漏是指计算机可用内存的逐渐减少. 当程序持续无法释放其使用的临时内存时就会发生. JavaScript的web应用也会经常遇到在原生应用程序中出现的内存相关的问题,如 泄漏和溢出,web应用也需要应对 垃圾回收停顿. 尽管JavaScript使用垃圾回收进行自动内存管理,但有效的(effective)内存管理依然很重要.

JavaScript 启动性能瓶颈分析与解决方案

- - SegmentFault 最新的文章
JavaScript 启动性能瓶颈分析与解决方案 翻译自 Addy Osmani 的. JavaScript Start-up Performance,从属于笔者的 Web 前端入门与工程实践. 本文已获得原作者授权,为InfoQ中文站特供稿件,首发地址为 这里;如需转载,请与InfoQ中文站联系.

Javascript诞生记

- Milido - 阮一峰的网络日志
二周前,我谈了一点Javascript的历史. 今天把这部分补全,从历史的角度,说明Javascript到底是如何设计出来的. 只有了解这段历史,才能明白Javascript为什么是现在的样子. 我依据的资料,主要是Brendan Eich的自述. "1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.

JavaScript,你懂的

- dylan - keakon的涂鸦馆
经常有人问我,JavaScript应该怎么学. 先学基本语法,如果曾学过C等语言,应该1小时内就能掌握了. 再去使用内置的函数、方法和DOM API,熟悉它能干什么;而在学习DOM API的过程中,你还不得不与HTML和CSS打交道. 然后弄懂匿名函数和闭包,学会至少一个常用的JavaScript库(例如jQuery).