优雅的处理vue项目异常实战记录


Posted in Javascript onJune 05, 2019

背景

  • 你还在为处理Uncaught (in promise) ReferenceError烦恼吗?
  • 你还在为捕获异常反复的写try catch吗?
  • 你还在为每一个promise写catch吗?

是时候一站式统一处理异常!!!(针对vue项目)

全局异常捕获

Vue.config.errorHandler = function (err, vm, info) {
 // 指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。
 
 // handle error
 // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
 // 只在 2.2.0+ 可用 
}

注意:面对异常处理,同步异常和异步异常应该区别对待分别处理。

vue核心源码剖析

通过阅读源码看一下vue是如何将Vue.config.errorHandler接口暴露给使用者。

同步异常处理方案

// 定义异常处理函数,判断用户是否自定义Vue.config.errorHandler,定义则直接调用,未定义执行vue本身异常处理。
function globalHandleError(err, vm, info) {
 if (Vue.config.errorHandler) {
  try {
   return config.errorHandler.call(null, err, vm, info)
  } catch (e) {
   logError(e, null, 'config.errorHandler');
  }
 }
 logError(err, vm, info);
}
try {
 // vue正常执行代码被包裹在try内,有异常会调用globalHandleError
} catch (e) {
 globalHandleError(e, vm, '对应信息');
}

异步异常处理方案

// 定义异步异常处理函数,对于自身没有捕获异常的promise统一执行catch
function invokeWithErrorHandling(
 handler,
 context,
 args,
 vm,
 info
) {
 var res;
 try {
  res = args ? handler.apply(context, args) : handler.call(context);
  if (res && !res._isVue && isPromise(res) && !res._handled) {
   res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); });
   // 异步代码例如promise可以统一为其定义Promise.prototype.catch()方法。
   res._handled = true;
  }
 } catch (e) {
  handleError(e, vm, info);
 }
 return res
}

// 所有的钩子函数调用异常处理函数
function callHook(vm, hook) {
 var handlers = vm.$options[hook];
 // 为所有钩子增加异常处理
 var info = hook + " hook";
 if (handlers) {
  for (var i = 0, j = handlers.length; i < j; i++) {
   invokeWithErrorHandling(handlers[i], vm, null, vm, info);
  }
 }
}

知识延伸

// vue接口是能处理同步异常以及部分钩子中的异步异常,对于方法中的异常无法有效处理,我们可以仿照源码增加方式中的异步异常处理,避免为每一个promise写catch
Vue.mixin({
 beforeCreate() {
  const methods = this.$options.methods || {}
  Object.keys(methods).forEach(key => {
   let fn = methods[key]
   this.$options.methods[key] = function (...args) {
    let ret = fn.apply(this, args)
    if (ret && typeof ret.then === 'function' && typeof ret.catch === "function") {
     return ret.catch(Vue.config.errorHandler)
    } else { // 默认错误处理
     return ret
    }
   }
  })
 }
})

完整代码

下面是全局处理异常的完整代码,已经封装成一个插件

errorPlugin.js

/**
 * 全局异常处理
 * @param {
 * } error 
 * @param {*} vm 
 */
const errorHandler = (error, vm, info) => {
 console.error('抛出全局异常')
 console.error(vm)
 console.error(error)
 console.error(info)
}
let GlobalError = {
 install: (Vue, options) => {
 /**
  * 全局异常处理
  * @param {
  * } error 
  * @param {*} vm 
  */
  Vue.config.errorHandler = errorHandler
  Vue.mixin({
   beforeCreate() {
    const methods = this.$options.methods || {}
    Object.keys(methods).forEach(key => {
     let fn = methods[key]
     this.$options.methods[key] = function (...args) {
      let ret = fn.apply(this, args)
      if (ret && typeof ret.then === 'function' && typeof ret.catch === "function") {
       return ret.catch(errorHandler)
      } else { // 默认错误处理
       return ret
      }
     }
    })
   }
  })
  Vue.prototype.$throw = errorHandler
 }
}
export default GlobalError

使用

// 在入口文件中引入
import ErrorPlugin from './errorPlugin'
import Vue from 'vue'
Vue.use(ErrorPlugin)

写在最后

增加全局异常处理有助于

  • 提高代码健壮性
  • 减少崩溃
  • 快速定位bug

资料参考

  • github.com/vuejs/vue/b…
  • cn.vuejs.org/v2/api/#err…

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript 有趣而诡异的数组
Apr 06 Javascript
超简单的jquery的AJAX用法
May 10 Javascript
jquery实现邮箱自动补全功能示例分享
Feb 17 Javascript
jQuery焦点图切换特效代码分享
Sep 15 Javascript
简单的分页代码js实现
May 17 Javascript
BootStrap 智能表单实战系列(五) 表单依赖插件处理
Jun 13 Javascript
vue.js实现请求数据的方法示例
Feb 07 Javascript
angularjs实现的前端分页控件示例
Feb 10 Javascript
angular中不同的组件间传值与通信的方法
Nov 04 Javascript
详解Vue源码学习之callHook钩子函数
Jul 25 Javascript
Vue-router 切换组件页面时进入进出动画方法
Sep 01 Javascript
JavaScript如何使用插值实现图像渐变
Jun 28 Javascript
原生JS使用Canvas实现拖拽式绘图功能
Jun 05 #Javascript
Node.js 路由的实现方法
Jun 05 #Javascript
JS实现动态添加外部js、css到head标签的方法
Jun 05 #Javascript
JS函数动态传递参数的方法分析【基于arguments对象】
Jun 05 #Javascript
jQuery操作cookie的示例代码
Jun 05 #jQuery
JS实现从对象获取对象中单个键值的方法示例
Jun 05 #Javascript
微信小程序如何实现全局重新加载
Jun 05 #Javascript
You might like
PHP开发中常用的三个表单验证函数使用小结
2010/03/03 PHP
解析php mysql 事务处理回滚操作(附实例)
2013/08/05 PHP
php顺序查找和二分查找示例
2014/03/27 PHP
php实现建立多层级目录的方法
2014/07/19 PHP
php通过记录IP来防止表单重复提交方法分析
2014/12/16 PHP
php5与php7的区别点总结
2019/10/11 PHP
js null undefined 空区别说明
2010/06/13 Javascript
JS控制文本框textarea输入字数限制的方法
2013/06/17 Javascript
node.js中的events.emitter.removeListener方法使用说明
2014/12/10 Javascript
jquery实现不包含当前项的选择器实例
2015/06/25 Javascript
JavaScript保留关键字汇总
2015/12/01 Javascript
js 两个日期比较相差多少天的实例
2017/10/19 Javascript
深入理解Node module模块
2018/03/26 Javascript
解决Vue axios post请求,后台获取不到数据的问题方法
2018/08/11 Javascript
Node.js + express实现上传大文件的方法分析【图片、文本文件】
2019/03/14 Javascript
Vue事件修饰符native、self示例详解
2019/07/09 Javascript
微信小程序实现底部弹出框
2020/11/18 Javascript
[57:22]完美世界DOTA2联赛PWL S2 FTD vs PXG 第二场 11.27
2020/12/01 DOTA
python 把数据 json格式输出的实例代码
2016/10/31 Python
Python标准库inspect的具体使用方法
2017/12/06 Python
Python实现的径向基(RBF)神经网络示例
2018/02/06 Python
Django 多语言教程的实现(i18n)
2018/07/07 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
【python】matplotlib动态显示详解
2019/04/11 Python
python实现动态数组的示例代码
2019/07/15 Python
Python with关键字,上下文管理器,@contextmanager文件操作示例
2019/10/17 Python
使用TensorFlow-Slim进行图像分类的实现
2019/12/31 Python
python 装饰器重要在哪
2021/02/14 Python
HTML5 Canvas中绘制椭圆的4种方法
2015/04/24 HTML / CSS
Html5移动端网页端适配(js+rem)
2021/02/03 HTML / CSS
Athleta官网:购买女士瑜伽服、技术运动服和休闲运动服
2020/11/12 全球购物
什么是GWT的Entry Point
2013/08/16 面试题
旅游与酒店管理的自我评价分享
2013/11/03 职场文书
销售员试用期自我评价
2014/09/15 职场文书
离婚财产分隔协议书
2014/10/23 职场文书
2015年基层党建工作汇报材料
2015/06/25 职场文书