前言在错误监控中,常用的方法有:全局捕获Promise未处理异常unhandledrejection事件window.onerror全局捕获error事件forVue.jserrorsReporting需要使用它提供的Vue.config.errorhandler方法,但是一旦错误被这个方法捕获到,就不会抛到控制台。如果需要自己写一个错误监控,理论上我们只是捕获并上报错误,但是最好不要阻止错误在控制台显示,所以本文就两三个东西进行分析。如果大家有兴趣,或者正在为自己的项目写报错插件,可以一起分析。在本文中,我们将从错误监控的角度来分析和使用errorhandler。Vue项目报错正常显示示例代码如下:exportdefault{created(){leta=null;如果(a.length>1){//...}}};正常情况下,上面的代码会报错:vueprojectErrorcaptureanditsdefects继上面,我们尝试通过Vue.config.errorHander来捕获:Vue.config.errorHandler=(err,vm,info)=>{console.log('Comein~');}exportdefault{created(){leta=null;如果(a.length>1){//...}}};那么控制台不会抛出错误:那么在错误监控系统中,理论上我们只是去捕获错误报告,而不是拦截错误报告,那么如何才能将错误抛到控制台呢?很简单,只需要添加一个console.error(err):Vue.config.errorHandler=(err,vm,info)=>{console.log('进来~');console.error(err);~~~~}exportdefault{created(){leta=null;如果(a.length>1){//...}}};控制台会得到如下截图:那么就ok了,报错给我们你可以在Vue.config.errorHandler中做,然后在Vue中补上这个“短板”,这样就可以继续抛错了通常情况下。那么此时的报错函数(比如这个函数是captureError())应该这样调用:Vue.config.errorHandler=(err,vm,info)=>{console.log('进来~');//错误上报给收集错误的平台captureError(err);}exportdefault{created(){leta=null;如果(a.length>1){//...}}};errorHandler源码分析是为了获取想知道Vue中是如何处理错误的,先看下源码(注释也顺便写了):functionglobalHandleError(err,vm,info){//获取全局配置,判断是否设置处理函数,默认未定义//已经配置if(config.errorHandler){try{//执行errorHandlerreturnconfig.errorHandler.call(null,err,vm,info)}catch(e){//\#如果开发者在errorHandler函数中手动抛出相同的错误信息throwerr\#判断err信息是否相等,避免记录两次if(e!==err){logError(e,null,'config.errorHandler')}}}//无配置,常规输出logError(err,vm,info)}functionlogError(err,vm,info){if(process.env.NODE_ENV!=='production'){warn(`Errorin${info}:"${err.toString()}"`,vm)}/*istanbul忽略其他*/if((inBrowser||inWeex)&&typeofconsole!=='undefined'){console.error(err)}else{throwerr}}解读源码中Bugsnag-js和sentry如何处理?先看bugsnag-js中的做法:module.exports={name:'vue',init:(client,Vue=window.Vue)=>{if(!Vue)thrownewError('cannotfindVue')//想想为什么这样做constprev=Vue.config.errorHandlerconsthandler=(err,vm,info)=>{consthandledState={severity:'error',unhandled:true,severityReason:{type:'unhandledException'}}constreport=newclient.BugsnagReport(err.name,err.message,client.BugsnagReport.getStacktrace(err),handledState,err)report.updateMetaData('vue',{errorInfo:信息,组件:vm?formatComponentName(vm,true):undefined,props:vm?vm.$options.propsData:undefined})client.notify(report)if(typeofconsole!=='undefined'&&typeofconsole.error==='函数')安慰。错误(错误)如果(typeofprev==='function')prev。call(this,err,vm,info)}//想想为什么要这样做Vue.config.errorHandler=handlerreturnnull}}我们看一下sentry中的方法:functionvuePlugin(Raven,Vue){Vue=Vue||窗户。视图;//如果Vue不在页面上则退出if(!Vue||!Vue.config)return;//你为什么这么做?var_oldOnError=Vue.config.errorHandler;Vue.config.errorHandler=functionVueErrorHandler(error,vm,info){//...//报告Raven.captureException(error,{extra:metaData});if(typeof_oldOnError==='function'){//为什么要这样做?_oldOnError.call(this,error,vm,info);}};}module.exports=vuePlugin;上面的“为什么要这样做”:AOP切面编程,保持上面原方法的纯粹性。
