一、js异常的捕获
1.window.onerror
当javascript运行发生错误时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror()。这是记录客户端错误并将其报告给服务器的最简单方法之一。
window.onerror = function(message, source, lineno, colno, error) { ... }
函数参数:
-
message
:错误信息(字符串)。可用于HTMLonerror=""
处理程序中的event
。 -
source
:发生错误的脚本URL(字符串) -
lineno
:发生错误的行号(数字) -
colno
:发生错误的列号(数字) -
error
:Error对象(对象)
window.onerror含有详细的error堆栈信息,存在error.stack中。遗憾的是stack属性是非标准的,并且其实现在不同的浏览器中也有所不同。幸运的是,有一些工具可以标准化堆栈属性,以便在浏览器之间保持一致。例如,raven-js使用TraceKit标准化错误字符串
上图为不同浏览器对各个参数的支持,某些浏览器没有错误对象,就没有堆栈跟踪属性。这意味着这些浏览器无法从onerror捕获的错误中检索有价值的堆栈信息。默认情况下,Raven.js(Sentry的JavaScript SDK)会谨慎地使用内置方法来尝试自动将代码包装在try / catch块中。这样做是为了尝试捕获所有脚本中的错误消息和堆栈跟踪信息,而不管它们来自何处。
2.script error的解决方式
另外,需要注意的是当加载自非同源的脚本中发生语法错误时,为避免信息泄露,语法错误的细节将不会报告,而代之简单的**"Script error."**
。这是浏览器所做的安全限制措施
解决方案1:
添加 crossorigin="anonymous" 属性。
添加跨域 HTTP 响应头:Access-Control-Allow-Origin: *
完成上述两步之后,即可通过 window.onerror 捕获跨域脚本的报错信息。
解决方案2:
难以在 HTTP 请求响应头中添加跨域属性时,还可以考虑 try catch 这个备选方案。可以在 catch 语句中手动上报捕获的异常。如果你使用sentry的raven.js的话,你会发现你什么都不用做,他依然可以帮你捕获到一些错误的非常具体信息,关键就是raven源码中的install方法中调用的_instrumentTryCatch函数起了作用,他通过tryCatch的方式wrap了一些关键函数,使得这些函数里的报错能够捕获
3.资源加载错误的捕获
当一项资源(如<img>
或<script>
)加载失败,加载资源的元素会触发一个[Event
]接口的事件,并执行该元素上的onerror()
处理函数。这些error事件不会向上冒泡到window,不过能被window.addEventListener在捕获阶段捕获。
window.addEventListener('error', event => (){
// 处理错误信息
}, true);
// true代表在捕获阶段调用,false代表在冒泡阶段捕获。
但这里需要注意,使用window.onerror和window.addEventListener('error')都能捕获运行错误,但是window.onerror含有详细的error堆栈信息,存在error.stack中,所以我们选择使用onerror的方式对js运行时错误进行捕获。因此对addEventListener绑定的事件需要过滤避免重复上报,判断为资源错误的时候才进行上报。
4.未处理的promise错误
当promise被reject并且错误信息没有被处理的时候,会抛出一个unhandledrejection
这个错误不会被window.onerror以及window.addEventListener('error')捕获,但是有专门的window.addEventListener('unhandledrejection')方法进行捕获处理。