错误的分类
- 代码运行错误:也称为代码错误。这个错误一般在代码书写时造成的,比如语法错误、逻辑错误,这样的错误通常在开发或测试阶段就会被发现
- 资源加载错误:这个错误通常是找不到文件(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
- 能捕获包裹体内的同步执行错误。
window.onerror
- 能捕获所有同步执行错误。
- 能捕获普通异步任务错误。
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 类型的
结语
以上三种上报方式,可根据实际业务场景需求使用,可搭配可视化界面提供更好的数据展示以及处理方案