更多腾讯海量技术文章,请关注云加社区:https://cloud.tencent.com/developer
作者:vienwu
javascript 的出错我们应该都很熟悉,例如 xxx undefined,SyntaxError等。
我们 team 将出现错误的 javascript 代码取名为 badjs,也有一个开源的 badjs 项目,用于捕获和分析 js 错误,并提供了一些基础的报表数据分析。
捕获错误一般有两种方式:
使用window.onerror()捕获全局的js错误信息
使用try{...}catch(e){...}包裹需要执行的代码,获取error对象的属性定位错误并上报
第一种方式最简单,但当执行的js代码和我们的站点在不同域即跨域时,由于浏览器的安全限制,onerror()方法只能捕获到一个固定的错误代码 Script error.。
具体可参考这里:点击查看。
我们团队目前的业务基本都会将静态资源部署到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等
这里处理的原理比较简单,类似下面的代码:
这里还有一些兼容性的问题需要处理,例如在ie低版本中setTimtout和setInterval方法并不是function类型,而是object,所以无法使用改写function的方式进行包裹。类似的还有document.attachEvent方法也是object,不是function。
除了对以上方法的单独处理外,还有一些意外情况无法处理,例如:
第三方的插件的自定义事件,如flash播放器提供的一些用于播放控制的事件。
这些意外情况很难做全局的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,直接避免跨域问题
,这个思路也值得一试。
另外,错误上报数据和访问量等数据如果到结合一起分析,不仅可以更快速的定位问题,甚至可以实现监控自动告警等,当然这个也非常复杂。
领取专属 10元无门槛券
私享最新 技术干货