前端如何收集错误(原生,Vue)
如何捕获异常
JS异常
js异常的特点是,出现不会导致JS引擎崩溃,最多只会终止当前执行的任务。
比如一个页面有两个按钮,如果点击按钮导致页面发生异常,这个时候页面不会崩溃。
只是这个按钮的功能失效,其他按钮还会有效
上面的例子我们用setTimeout分别启动了两个任务。
虽然第一个任务执行了一个错误的方法。程序执行停止了。但是另外一个任务并没有收到影响。
其实如果你不打开控制台都看不到发生了错误。好像是错误是在静默中发生的。
下面我们来看看这样的错误该如何收集。
try-catch:
如果在函数中错误没有被捕获,错误会上抛。
控制台中打印出的分别是错误信息和错误堆栈。
读到这里大家可能会想那就在最底层做一个错误try-catch不就好了吗。
确实作为一个从java转过来的程序员也是这么想的。
但是理想很丰满,现实很骨感。我们看看下一个例子。
大家注意运行结果,异常并没有被捕获。
这是因为JS的try-catch功能非常有限一遇到异步就不好用了。
那总不能为了收集错误给所有的异步都加一个try-catch吧,太坑爹了。
其实你想想异步任务其实也不是由代码形式上的上层调用的就比如本例中的setTimeout。
大家想想eventloop就明白啦,其实这些异步函数都是就好比一群没娘的孩子出了错误找不到家大人。
当然我也想过一些黑魔法来处理这个问题比如代理执行或者用过的异步方法。
算了还是还是再看看吧。
异常任务捕获
window.onerror:
window.onerror 最大的好处就是同步任务、异步任务都可捕获。
onerror返回值
onerror还有一个问题大家要注意 如果返回true 就不会被上抛了。
不然控制台中还会看到错误日志。
监听error事件:
文件中的位置☟
window.addEventListener('error',() => {})
其实 onerror 固然好但是还是有一类异常无法捕获。这就是网络异常的错误。
比如下面的例子。
<img src="./xxxxx.png">
试想一下我们如果页面上要显示的图片突然不显示了,而我们浑然不知那就是麻烦了。
addEventListener就解决这个问题:
运行结果如下:
Promise异常捕获:
Promise 的出现主要是为了让我们解决回调地域问题。基本是我们程序开发的标配了。
虽然我们提倡使用 es7 async/await 语法来写。
但是不排除很多祖传代码还是存在Promise写法。
new Promise((resolve, reject) => {
abcxxx()
});
这种情况无论是onerror还是监听错误事件都是无法捕获的。
除非每个Promise都添加一个catch方法。
但显然,我们不能这样做.
window.addEventListener("unhandledrejection", e => {
console.log('unhandledrejection',e)
});
我们可以考虑将unhandledrejection事件捕获的错误抛出交由错误事件统一处理就可以了。
async/await异常捕获:
实际上async/await语法本质还是Promise语法。
区别就是async方法可以被上层的try/catch捕获。
如果不去捕获的话就会和Promise一样,需要用unhandledrejection事件捕获。
这样的话我们只需要在全局增加unhandlerejection就好了。
小结:
实际上我们可以将unhandledrejection事件抛出的异常再次抛出就可以统一通过error事件进行处理了。
最终用代码表示如下:
VUE工程
利用vue-cli工具直接创建一个项目。
为了测试的需要我们暂时关闭eslint 这里面还是建议大家全程打开eslint。
在vue.config.js进行配置
我们故意在(文件位置☟)
src/components/HelloWorld.vue
这个时候 错误会在控制台中被打印出来,但是错误事件并没有监听到。
errorHandle 句柄:
为了对Vue发生的异常进行统一的上报,需要利用vue提供的errorHandle句柄。
一旦Vue发生异常都会调用这个方法。
我们在src/main.js
文章转载自:从 0 到 1 搭建前端异常监控系统