前端错误处理、vue项目错误处理(异常采集、捕获、收集)
公司项目需要做错误采集,平时都是谷歌控制台调试查看错误的,那有什么办法可以收集到这些错误信息保存在数据库中呢,此时,压力来到了我这。。。
首先来看看都有哪些捕获异常的方式:
同步异常:
- try/catch: 任务流方式
- window.onerror:全局对象监听错误回调方式
- element.onerror:部分元素错误回调方式
- Vue.config.errorHandler:vue全局组件异常
- errorCaptured:vue组件异常生命周期钩子函数
异步异常:
实例演示
这种方式我们一般用来在预先知道哪段代码会出现异常然后我们将这段代码用try包起来用catch捕获其出现的异常。
先来看看处理同步异常
可以看到,try/catch可以正常捕获同步异常,接下来我们看看异步异常是否能被try/catch捕获
可以看到,无论是否定时器的异步异常还是promise的异步异常,使用try/catch都无法正常捕获。但是,其实对于promise异常来说,try/catch方式可以使用async/await来进行异常捕获的。
其具体原理可以参考博客 https://blog.csdn.net/qq_43497320/article/details/122675328
window.onerror是全局对象的一个事件监听处理函数,javascript产生的语法错误及运行错误可以触发error事件被window.onerror处理函数处理。
可以看到,window.onerror可以捕获同步异常和定时器异步异常,不能捕获promise异步异常。另外在vue项目中,如果同步异常出现在vue组件中,window.onerror是捕获不到的,不过在vue组件中的定时器异步异常还是可以通过window.onerror捕获到
首先mian.js设置window.onerror监听器
然后在home.vue组件中分别测试同步异常和定时器异步异常
在部分元素例如 img、script等标签加载失败的时候会触发该元素对象的error事件,设置该元素 element.onerror的监听程序可以捕获到这类异常,注意:这种异常不会冒泡到全局,所以window.onerror是监听不到的。
对于vue组件中的同步异常我们的全局的window.onerror捕获不到怎么办呢? 这时就得使用vue提供的 Vue.config.errorHandler 组件全局异常 和 errorCaptured 生命周期钩子函数了
由于vue中同步异常被内部的errorHandler捕获了,所以我们的window.onerror捕获不到,所以我们要想捕获vue组件中出现的同步异常,得从errorHandler中来捕获
首先main.js配置Vue.config.errorHandler
接着在home.vue组件中测试同步异常,然后该异常被Vue.config.errorHandler成功捕获
errorCaptured是vue组件中的生命周期的钩子函数,用于捕获当前组件及其后代组件产生的错误,如果该钩子函数返回false将会阻止error上传,也就是说,一个父子组件都定义了errorCaptured钩子函数,在该函数都没有返回false的情况下,如果子组件出现了异常(注意:不会调用发生异常组件的errorCaptured),父组件的errorCaptured => Vue.config.errorHandler都能依次捕获到异常。但如果有其中的errorCaptured返回false,则该异常不会再往上传输。接下来实例看看吧!
home.vue为父组件,helloworld.vue为子组件,其中同步异常发生在子组件中
可以看到,父组件的errorCaptured和Vue.config.errorHandler依次捕获了子组件产生的同步异常
这时我们把父组件的errorCaptured函数返回fasle看看
此时Vue.config.errorHandler就无法捕获到异常了
接着我们来看看promise产生的异常,正常来说如果是个异步的promise我们可以采用它本来提供的.then()的第二个参数回调或者.catch()来捕获
两种方式都一样,都可以正常捕获到被拒绝的promise,当然一个promise被拒绝了就会被最近一层的.catch()捕获到,对于以及被捕获的异常则不会继续往下一层传。
那如果我们有些promise没有被任何.catch()处理,那我们还要怎么捕获呢?
当有未被捕获的被拒绝的promise,会触发unhandledrejection事件,我们可以通过window.onunhandledrejection来捕获未被处理的promise异常
首先我们在main.js中配置window.onunhandledrejection,然后在任意组件中测试promise异常
可以看到window.onunhandledrejection可以捕获未被处理的promise异常,此时我们把组件中的异常用.catch()捕获看看
可以看到该promise异常以及被.catch()捕获了,所以我们window.onunhandledrejection就捕获不了该异常了。
最后我们来看看我们通过各种方式捕获到的各种不同的异常,大都有一个类似这样的信息。这其实就是一个异常对象(Error对象),我们也可以通过throw new Error()的方式抛出我们自己定义的异常
然后回到公司需要我收集异常信息,所以我得把这个对象弄到数据库去,一想到这个错误对象既然是个js对象,那我应该可以通过JSON.stringify()把它转成json字符串然后传到数据库去。
打印出来一脸懵逼,我数据呢?然后联想到了该错误对象的属性可能是不可枚举的 可以看下我的另一篇博客:js对象的那些事...可扩展特性(extensible)和对象的属性的四个特性(value、writable、enumerable、configurable) - 孤僻而冷漠 - 博客园 (cnblogs.com)
看了一下,好家伙还真是,最后参考了一下 (20条消息) JS中的Error对象及使用JSON.stringify() 序列化 Error_阿斯巴甜嘛的博客-CSDN博客 ,最后一顿操作
最后,终于是想要的样子了。