关于javascript错误捕获

```

javascript的出错我们应该都很熟悉,例如`xxx undefined`,`SyntaxError`等。

我们team将出现错误的javascript代码取名为badjs,也有一个开源的badjs项目,用于捕获和分析js错误,并提供了一些基础的报表数据分析。


#### 捕获错误一般有两种方式:

* 使用window.onerror()捕获全局的js错误信息
* 使用`try{...}catch(e){...}`包裹需要执行的代码,获取error对象的属性定位错误并上报


第一种方式最简单,但当执行的js代码和我们的站点在不同域即跨域时,由于浏览器的安全限制,onerror()方法只能捕获到一个固定的错误代码`Script error.`。
具体可参考这里:[点击查看](http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#runtime-script-errors)

我们团队目前的业务基本都会将静态资源部署到cdn服务器,和站点处于不同域,所以需要解决跨域问题。

跨域问题可以通过服务器端设置`access-control-allow-orgin:*`解决,但并不完美。这个问题更深入的信息可以参考这里:https://github.com/BetterJS/badjs-report/issues/3

第二种方式是手动包裹一些要检测的代码,没有跨域问题并且可以获取到err的对象的详细出错信息。
这种方式相对麻烦一些,但可以通过全局的hook,处理大部分情况,免除每次手动写try...catch的烦恼。

我们都知道js代码的执行是通过事件和定时器触发执行的,所以理论上将事件触发时的回调、定时器的回调包裹即可。

我们的badjs项目主要是通过第二种方式实现,并根据现有的业务,对以下几种方法进行了处理:

* `define()`,`require()`等方法
* jQuery封装的一些事件,如`$.event.add`,`$.event.remove`,ajax等
* setTimeout setInterval等

这里处理的原理比较简单,类似下面的代码:

function define(){ ... } var a = define; define = function(){ try{ a.apply(this,arguments); }catch(e){ ...错误上报 } };

这里还有一些兼容性的问题需要处理,例如在ie低版本中setTimtout和setInterval方法并不是`function`类型,而是`object`,所以无法使用改写`function`的方式进行包裹。类似的还有`document.attachEvent`方法也是`object`,不是`function`。


除了对以上方法的单独处理外,还有一些意外情况无法处理,例如:

* window.onload,Image.prototype.onerror等浏览器和dom的事件,这类方法无法直接改写function
* 第三方的插件的自定义事件,如flash播放器提供的一些用于播放控制的事件。
* 新的一些api,如FileReader.prototype.onload等

这些意外情况很难做全局的hook,所以只好手动try...catch。
我们的badjs也提供了一个便捷的api,例如源代码是这样:

var img = new Image(); img.onload = function(){ ... };

使用tryjs包裹

var img = new Image(); img.onload = tryJs.spyCustom(function(){ ... }); ```

除此之外,try...catch能获取的err对象在各不同的浏览器之间,也有一些差异。好在有人已经做一个页面展示详细的差异,参考url: http://broofa.com/tests/ErrorProperties.htm。

一些其他的补充

回到捕获js错误这件事本身,是为了更好的监控并定位错误,帮助我们改善代码质量,所以kael也提到另外一个思路,可以灰度一部分用户,直接使用主域而不是cdn的js,直接避免跨域问题,这个思路也值得一试。

另外,错误上报数据和访问量等数据如果到结合一起分析,不仅可以更快速的定位问题,甚至可以实现监控自动告警等,当然这个也非常复杂。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏全栈数据化营销

6款超级提高效率的chrome插件

是一款网页标签插件,我们通常会因为工作需要,去浏览大量的网页,结果是,打开的网页越来越多,又不敢轻易关掉,害怕再也找不回来。 One Tab可以让你把网页瞬间集...

1132
来自专栏ImportSource

Gitlab.com宕机始末

接上集:Gitlab.com误删数据最近动态:恢复60% 14小时前 数据库恢复60%; 13小时前 gitlab在国外某非著名视频网站直播自己的数据库恢复进...

4066
来自专栏姬小光

姬小光前端小讲堂【第006期】

在前几期的成果中,我们做出来的页面只有一些“静态”的内容,只能给用户大眼瞪小眼的看,那么别人家的网页上那些飞来飞去的,若隐若现的东西都是咋搞的呢?

902
来自专栏性能与架构

页面静态化

静态化的优势 (1)提高页面的打开速度 直接访问静态页面,无需任何动态处理,打开速度大幅提高 (2)降低服务器的访问压力 不需要应用服务器对动态程序的计算,也不...

3977
来自专栏漏斗社区

工具|nessus自定义扫描策略

我们是谁? nessus工具! 我们要做什么? 扫描漏洞! 什么时候扫? 天天扫! 序言 有些时候我们并不希望进行全面的扫描和检测,仅需要针对某些漏洞进行安全...

6116
来自专栏IT技术精选文摘

分布式存储理论与实践初探 (二)

数据分布 分布式存储系统需要将数据分布到多个节点,并在多个节点之间实现负载均衡。常见的数据分布的方式有两种:一种是哈希分布,如一致性哈希,典型的系统是Amazo...

2316
来自专栏EAWorld

8种至关重要OAuth API授权流与能力

在本文中,Curity的Daniel Lindau概述了重要的OAuth授权流程和能力。

801
来自专栏知晓程序

电商/票务类小程序必读,如何用小程序推送消息?

通常,服务方向用户推送的消息都带有通知性质,文案也相对固定。服务方将这类固定的文案制作成模板,这些文案就可以快速重复使用。

1362
来自专栏达摩兵的技术空间

前端文件下载通识篇

前端如何实现下载文件呢?随着前端技术的发展,越来越多的前端需求中会出现下载文件这样的需求。

6952
来自专栏24K纯开源

使用VS2010开发Qt程序的一点经验

导读      相比于Qt Creator,我更喜欢用VS2010来进行开发。虽然启动时间相对较慢,但是VS下强大的快捷键和丰富的插件,以及使用多年的经验,都让...

2918

扫码关注云+社区

领取腾讯云代金券