优雅处理前端异常
一、为什么要处理异常?
1 增强用户体验
2 远程定位问题
3 未雨绸缪 发现问题
4 无法浮现问题 尤其是移动端 机型 系统都是问题
5 完善的前端方案 前端监控系统
二、需要处理哪些异常
1、js预发错误 代码异常
2、ajax请求异常
3、静态资源家在异常
4、promise异常
5、iframe异常
6、跨域script error
7、崩溃和卡顿
Try-Catch的误区
try-catch只能捕获同步的运行时错误。对语法和异步的错误无能为力,捕获不到。
1、同步运行时错误
同步运行时错误.png
2、不能捕获具体的语法错误,只有一个语法错误提示
这个错误基本上没有啥用.png
3、异步错误
image.png
异步异常 捕获不到
四、window.onerror不是万能的
当js运行时错误发生时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror
/**
message: 错误信息
source: 出错文件
lineno: 行号
error: 错误对象
*/
window.onerror = function(message, source, lineno, colno, error){
console.log('异常捕获', {message, source, lineno, colno, error})
}
1、同步信息错误
window.error同步信息出错.png
2、语法错误
语法信息错误.png
3、模拟异步运行时的错误
setTimeout(() => {
michael
}, 3000)
异步错误.png
补充一点:window.onerror 函数只有返回true的时候,异常才不会向上抛出,否则控制台还是会显示Uncaught Error: XXXXXXXX
注意:
onerror最好写在所有的js脚本的前面,否则有可能捕获不到错误。
onerror无法捕获语法错误
五、winodw.addEventListener 静态资源加载异常
当资源加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror处理函数
window.addEventListener('error', function(error){
console.log('捕获到异常',error)
}, true)
image.png
六、Promise Catch
primise中使用catch可以获取到异步的error, 但是如果忘了怎么办
解决方案:为了防止有漏掉的Promise异常,建议在全局增加一个对unhandlerejection的监听,用来全局监听 Uncaught Promise Error
window.addEventListener('unhandledrejection', function(e) {
e.preventDefault()
console.log(e)
return true
})
Promise.reject('error')
错误信息.png
七、vue errorHandler
Vue.config.errorHandler = (err, vm, info) => {
console.error('通过vue errorHandler捕获的错误');
console.error(err);
console.error(vm);
console.error(info);
}
八、react中异常捕获
componentDidCatch(error, info){
}
注意点:error boundaries并不会捕获下面错误
1、事件处理器
2、异步代码
3、服务端的渲染代码
4、在error boundaries区域内的错误
九、iframe异常
<iframe src="./frame.html"></iframe>
window.frames[0].onerror = function(message, source, lineno, colno, error){
console.log('异常', { message, source, lineno, colno, error })
return true
}
十、Script error
基本上跨域问题
十一、崩溃和卡顿
利用window对象的load和beforeunload事件实现了网页崩溃的监控。
window.addEventListener('load', function(){
sessionStorage.setItem('good_exit', 'pending')
setInterval(function(){
sessionStorage.setItem('time_before', new Date().toString())
}, 1000)
})
window.addEventListener('beforeunload', function(){
sessionStorage.setItem('good_exit', 'true')
})
if(sessionStorage.getItem('good_exit') && sessionStorage.getItem('good_exit') !== 'true'){
alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash'))
}
2、基于以下原因,我们可以使用 Service Worker 来实现网页崩溃的监控:
Service Worker 有自己独立的工作线程,与网页区分开,网页崩溃了,Service Worker 一般情况下不会崩溃;Service Worker 生命周期一般要比网页还要长,可以用来监控网页的状态;网页可以通过 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW 发送消息。
十二 错误上报
1、通过ajax 风险:ajax本身也有报错风险,跨域问题
2、动态创建img标签的形式
function report(error){
let url = 'http://www.baicuu.com'
new Image().src = `${url}?logs=${error}`
}
收集信息太多怎么办?如何减少服务器的压力
Report.send = function(data){
if(Math.random < 0.3) {
send(data)
}
}
视情况定,用户特征等等
十三 总结
如何优雅的处理异常
1、可疑区增加try-catch
2、全局监控js异常
3、全局监控静态资源异常 window.addEventListener
4、
5、
6、监控网页崩溃:window对象的load 和 beforeunload
7、跨域crossOrigin
分类型解决异常