优雅处理前端异常

2020-07-23  本文已影响0人  Wang_Yong

一、为什么要处理异常?

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 发送消息。

知乎上关于service work来监控的方案

十二 错误上报

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
分类型解决异常

https://mp.weixin.qq.com/s/prf-mXexBh1Ie-ctq9FnzA

上一篇下一篇

猜你喜欢

热点阅读