Skip to main content

前端的错误监控和上报

· 6 min read
LIU

错误的分类

  • 代码运行错误:也称为代码错误。这个错误一般在代码书写时造成的,比如语法错误、逻辑错误,这样的错误通常在开发或测试阶段就会被发现
  • 资源加载错误:这个错误通常是找不到文件(404)或者是文件加载超时出现的

代码运行错误

SyntaxError 解析时发生语法错误

const abc

window.onerror捕获不到SyntxError,一般SyntaxError在构建阶段,或是本地开发阶段就会被抛出

TypeError 值不是所期待的类型

const person = void 0
person.name

ReferenceError 引用未声明的变量

abcdefg

RangeError 当一个值不在其所允许的范围或者集合中

(function fn ( ) { fn() })()

网络错误

ResourceError 资源加载错误

new Image().src = '/image/abc.png'

HttpError http请求错误

// 控制台运行
fetch('/lll/noneurl', {})

错误捕获

try…catch

  1. 能捕获包裹体内的同步执行错误。

window.onerror

  1. 能捕获所有同步执行错误。
  2. 能捕获普通异步任务错误。

window.addEventListener('error')

相比window.onerror,通过window.addEventListener的方式我们可以捕获资源加载的错误。

window.addEventListener('unhandledrejection')

上面3种常见的错误捕获方式,都不能捕获Promise任务的错误,有人会说了,Promise不是有自己的catch吗?是的,但是我相信大多数情况下开发者并不会为每一个Promise写一个catch,或者可能出现漏写的情况。Js为提供了一个事件监听: unhandledrejection 。它会在Promise 被reject(抛错)且没有被catch的时候触发。

window.addEventListener("unhandledrejection", event => {
console.warn(`unhandledrejection: ${event.reason}`);
});

handledrejection,它是在Promise的reject做了处理(catch)后触发

错误捕获方式同步任务普通异步任务Promise任务async任务资源加载语法错误
Try...catch××××
onerror××××
addEventListener('error')×××
addEventListener('unhandledrejection')××××

得出以上表格结果,首先可以看到语法错误,4种方式都不能捕获,但是一般语法错误不应该在执行阶段才发现,在编译以及测试环节就可以检查出,所以不考虑将其捕获。那么其他的异常错误通过 addEventListener('onerror') addEventListener('unhandledrejection') 的方式刚好能够覆盖5种异常错误的捕获

代码实现

window.addEventListener('onerror',()=>{
//执行上报处理
return false //取消默认事件
},true);//捕获阶段

window.addEventListener('unhandledrejection',()=>{
//e.reason
//执行上报处理
});//捕获阶段

数据上报

XMLHttpRequest

通过接口请求,将想要的数据传回给服务器,但有以下缺点:

  • 上报请求可能会阻塞业务

  • 有跨域的限制

  • 请求容易丢失

Image

var img = new Image();
img.width = 1;
img.height = 1;
img.src = 'https://lllllll.top/api/info.gif?data=${data}'

由于浏览器对资源文件的区别对待,为了解决上面的几个问题,我们可以通过创建一个1x1大小的图片进行异步加载的方式来上报。图片天然可跨域,又能兼容所有的浏览器。

但由于是一个get请求,上报的数据量在不同的浏览器下上限不一致(2kb-8kb),可能会出现超出长度限制而无法上报完整数据。

SendBeacon

navigator.sendBeacon() 方法可用于通过HTTP将少量数据异步传输到Web服务器。

没有跨域问题、不阻塞业务,能在页面unload阶段继续发送数据,唯一就是IE不支持

sendBeacon并不像XMLHttpRequest一样可以直接指定Content-Type,且不支持application/json等常见格式。data的数据类型必须是 ArrayBufferView 、 Blob 、 DOMString 或者 FormData 类型的

结语

以上三种上报方式,可根据实际业务场景需求使用,可搭配可视化界面提供更好的数据展示以及处理方案