前端错误监控原理刨析 | 青训营笔记

·  阅读 43

这是我参与「第四届青训营 」笔记创作活动的的第2天

前端监控这个词对于前端的新手同学应该都挺陌生,但是一个大型的业务,监控系统是必不可少,这关系这线上生产事故监测、定位起着非常重要的作用。

那么,前端监控系统到底监控着什么呢?

其实也很容易想到~

  • js错误
  • 资源错误
  • 请求错误
  • 框架错误

下面一个一个刨析如何捕获到这些错误。

js错误

js错误分位两类:编译错误运行时错误。一般编译错误在开发时就可以发现了,但是运行时错误则不一定,因为运行时错误发生的原因是多种多样的,很难完全预测。

对于这类错误,我们很容易想到try...catch,以前面试被问到如何监控js错误,我也回答了这个。这个确实可行,但是有缺陷。

原因:

  • 没办法捕捉到全局的错误事件;
  • 无法预测所有可能发生错误的代码,非要杠的话,那就是写满屏的try catch,可读性非常差。

其实window对象中提供了一个onerror事件用于捕获js运行时错误。

window.onerror = function(msg, source, lineno, colno, error) {
  // 参数分别为错误消息、错误源代码、行号、列号、错误对象
  // 可以在这里上报错误
  // 错误不会抛出控制台
}
复制代码

但是吧,这种方式也是有缺陷的,它只能同时绑定一个函数,对于多个脚本文件想要绑定不同的方法,对不起,它做不到!

但是呢,也不是没有其它方法,可以通过addEventListener来监听error事件。

window.addEventListener('error', (event) => {
  // 参数聚合在error对象
  // 上报错误
}, true)
复制代码

那,是不是这种方法就完美了呢?当然不是,首先这种方式会在控制台抛出错误,另外无论是window.onerror还是addEventListener('error', cb)都是捕获不到Promise的错误的。

Promise相关的错误有两种类型:

  • unhandledrejection
  • rejectionhandled

但是呢,也还是有办法的~

// unhandledrejection 推荐方案 
window.addEventListener('unhandledrejection', (event) => { 
  console.log(event) 
 }, true); 

// unhandledrejection 备选方案 
window.onunhandledrejection = function (error) { 
  console.log(error) 
} 

// rejectionhandled 推荐方案 
window.addEventListener('rejectionhandled', (event) => { 
  console.log(event) 
}, true); 

// rejectionhandled 备选方案 
window.onrejectionhandled = function (error) { 
  console.log(error)
}
复制代码

资源错误

资源错误和捕获js执行错误方法是一样的,但是要判断是不是资源错误,还得另加判断。

核心的一个知识点就是脚本错误的错误对象原型链上有ErrorEvent,而资源错误则是Event

window.addEventListener('error', (event) => { 
  if (event instanceof ErrorEvent) { 
    console.log('脚本错误') ;
  } else if (event instanceof Event) { 
    console.log('资源错误') 
  } 
}, true);
复制代码

请求错误

这里分为两种情况:

  1. 使用ajax/fetch发起请求

需要重写ajax/fetch方法,加入上报错误内容。

  1. 使用axios发起请求

直接在请求拦截器上报错误。

框架错误

Vue

  • 钩子函数errorCaptured
errorCaptured(error, vm, info){
  // 参数:错误,vue实例,哪个钩子发生错误的相关消息
}
复制代码
  • 全局捕获errorHandler
Vue.config.errorHandler = function (error, vm, info) { 
  // 上报错误
}
复制代码

React

  • getDerivedStateFromError
static getDerivedStateFromError(error) { 
  // 上报错误
}
复制代码
  • ErrorBoundary
componentDidCatch(error, info) {
  // 上报错误
}
复制代码

End

有错误欢迎评论指出~

分类:
阅读
标签:
收藏成功!
已添加到「」, 点击更改