vue修复watch
前言的BUG之前的项目中,需要收集并上报全局错误。最后头疼的是Vuewatch中的异步错误无法上报到errorHandler,然后有一天我再次尝试阅读Vue代码时,发现他在2.6.13版本修复了这个问题,开心!!!比如可以切换Vue的版本号看看效果。你会发现<=2.6.12版本的watch不会捕获异步错误。
复制代码Vue是如何解决的2.6.12Vue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{constvm:组件=thisif(isPlainObject(cb)){returncreateWatcher(vm,expOrFn,cb,options)}options=options||{}options.user=true//Watcher中的执行回调函数和下面一样,只是不要贴代码constwatcher=newWatcher(vm,expOrFn,cb,options)if(options.immediate){try{//直接执行回调函数cb.call(vm,watcher.value)}catch(error){handleError(error,vm,`callbackforimmediatewatcher"${watcher.expression}"`)}}returnfunctionunwatchFn(){watcher.teardown()}}复制代码2.6.13Vue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{constvm:Component=thisif(isPlainObject(cb)){returncreateWatcher(vm,expOrFn,cb,options)}选择离子=选项||{}options.user=true//Watcher中回调函数的执行和下面一样,就不贴代码了constwatcher=newWatcher(vm,expOrFn,cb,options)if(options.immediate){constinfo=`callbackforimmediatewatcher"${watcher.expression}"`pushTarget()//使用此函数执行回调函数invokeWithErrorHandling(cb,vm,[watcher.value],vm,info)popTarget()}returnfunctionunwatchFn(){watcher.teardown()}}复制代码并比较版本。我们发现两个版本的区别在于回调函数的执行方式发生了变化。回调函数通过invokeWithErrorHandling执行。如果是promise,会被handleError捕获并报告exportfunctioninvokeWithErrorHandling(handler:Function,context:any,args:null|any[],vm:any,info:string){让res试试{res=args?handler.apply(context,args):handler.call(context)if(res&&!res._isVue&&isPromise(res)&&!res._handled){res.catch(e=>handleError(e,vm,info+`(Promise/async)`))//issue#9511//避免在嵌套调用时多次触发catchres._handled=true}}catch(e){handleError(e,vm,info)}returnres}复制代码想着可能有人会问,为什么不自己尝试catch报错信息呢,不然这个有什么用呢?试着抓住自己,重复工作量巨大。这是对Vue的一个小修复,但是对于一个在线的项目来说,如果你不能把你所有的错误都报出来,那么有些地方可能会影响用户体验,造成用户的流失,甚至会导致公司财产的损失。Vue如何收集和报错对于我们开发者来说,最好不要手动报错,这样会带来很多重复性的工作。我们最好只关注我们正常的业务逻辑,而对于Vue项目来说,Vue会自动报我们的错误,只要我们保证一定的写法,错误就不会丢失。第一步,我们只需要一个地方全局报错,就是Vue的errorHandler。Vue将向此函数报告所有错误。可以直接申请哨兵,也可以在该函数中调用后台报错接口。第二步,我们确定报错的地方。接下来要做的是确保所有的错误都能被Vue捕捉到。同步任务的错误会被直接捕获,异步任务的错误必须按照一定的方式来写。在异步错误项目中,我们大多是和后台交互的,如下——这是我在项目中看到的最常见的方式,一旦使用then来处理异步任务,就意味着我们的错误不会被Vue捕获,如果我们有是then回调函数中的错误,我们要在最后写一个.catch来捕获then回调函数中的错误。这种写法给我们开发人员增加了很多工作量。mounted(){//不会捕获错误this.getData()},methods:{getData(){http.get('xxx').then(data=>{//xxx},error=>{//只能自己报异步错误})}}代码重复写法2我们只需要将我们then的写法换成asyncawait,所有的错误都会被捕获,更加简洁asyncmounted(){//使用awaitcanAnasynchronouserrorwascatchedawaitthis.getData()},methods:{asyncgetData(){constdata=awaithttp.get('xxx')//xxx}}如何保证大家使用异步语法开发如果你的Everyoneintheproject都能遵守这种写法,那你就不用再看了。对于开发项目,开发者不可控,编码风格千变万化。就算记住了哪种写法,实际开发中也会疏忽,可以用工具解决,不用口头上去约束。借助eslint,我们可以很容易的根据eslint制定一套规则,但是有些规则是没有的,需要自己去开发。针对上述异步语法的约束,我写了一个插件:eslint-plugin-leon-rule,大家可以参考下载源码或者使用。最后,如果您觉得这篇文章对您有点帮助,请点个赞。或者可以加入我的开发交流群:1025263163互相学习,我们会有专业的技术解答。如果您觉得这篇文章对您有用,请给我们的开源项目一个小星星:https://gitee。com/中邦科技/CRMEB非常感谢!