浅出Vue 错误处理机制errorCaptured、errorHandler
引子
JavaScript本身是一个弱类型语言,项目中容易发生错误,做好网页错误监控,能帮助开发者迅速定位问题,保证线上稳定。
vue项目需接入公司内部监控平台,本人之前vue errorHooks不甚了解, 决定探一探?
介绍 errorHandler、errorCaptured
文档传送门: errorHandler、errorCaptured
errorHandler
指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例
Vue.config.errorHandler = function (err, vm, info) {#处理错误信息, 进行错误上报#err错误对象#vm Vue实例#`info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子#只在 2.2.0+ 可用
}
复制代码
版本分割点
- 2.2.0 起,捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩溃
- 2.4.0 起,也会捕获 Vue 自定义事件处理函数内部的错误
- 2.6.0 起,也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理
errorCaptured
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播
错误传播规则
- 默认情况下,如果全局的 config.errorHandler定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报
- 如果一个组件的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。
- 如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler,不能捕获异步promise内部抛出的错误和自身的错误
- 一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了且应该被忽略”。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler
错误信息示例 errorHandler、errorCaptured
光说不练,说了白干,呈上结果供各位看官老爷查看
mounted hook 写入未定义的变量,例如:a
mounted() { a }
- Vue.config.errorHandler err、vm、info
- Vue.config.errorHandler 抛出同样的错误 throw err
globalHandleError函数有 e !== err 判断防止log两次错误 - Vue.config.errorHandler 抛出新的错误 throw new Error('你好毒')
- errorCaptured (err, vm, info) => ?Boolean 类似于React 错误处理边界
<error-boundary><another-component/>
</error-boundary>
复制代码
Vue.component('ErrorBoundary', {data: () => ({ error: null }),errorCaptured (err, vm, info) {this.error = `${err.stack}\n\nfound in ${info} of component`return false},render (h) {if (this.error) {return h('pre', { style: { color: 'red' }}, this.error)}// ignoring edge cases for the sake of demonstrationreturn this.$slots.default[0]}
})
复制代码
正文
copy 半天官网文档,你是copy忍者吗☺,各位看官老爷,请往下面看,注意自己使用时的Vue版本,避免err抓取不到?
解读error.js源码
Vue 源码中,异常处理的逻辑放在 /src/core/util/error.js 中
handleError、globalHandleError、invokeWithErrorHandling、logError
- handleError
在需要捕获异常的地方调用。首先获取到报错的组件,之后递归查找当前组件的父组件,依次调用errorCaptured 方法。在遍历调用完所有 errorCaptured 方法、或 errorCaptured 方法有报错时,调用 globalHandleError 方法 - globalHandleError
调用全局的 errorHandler 方法,如果 errorHandler 方法自己又报错了呢?生产环境下会使用 console.error 在控制台中输出 - invokeWithErrorHandling 更好的异步错误处理,当时写这篇文章时,git history显示小右哥,一周之前敲的代码,瞬间透心凉,心飞扬
- logError
判断环境,选择不同的抛错方式。非生产环境下,调用warn方法处理错误
errorCaptured 和 errorHandler 的触发时机都是相同的,不同的是 errorCaptured 发生在前,且如果某个组件的 errorCaptured 方法返回了 false,那么这个异常信息不会再向上冒泡也不会再调用 errorHandler 方法
/* @flow */
# Vue 全局配置,也就是上面的Vue.config
import config from '../config'
import { warn } from './debug'
# 判断环境
import { inBrowser, inWeex } from './env'
# 判断是否是Promise,通过val.then === 'function' && val.catch === 'function', val !=== null && val !== undefined
import { isPromise } from 'shared/util'
# 当错误函数处理错误时,停用deps跟踪以避免可能出现的infinite rendering
# 解决以下出现的问题https://github.com/vuejs/vuex/issues/1505的问题
import { pushTarget, popTarget } from '../observer/dep'export function handleError (err: Error, vm: any, info: string) {// Deactivate deps tracking while processing error handler to avoid possible infinite rendering.pushTarget()try {# vm指当前报错的组件实例if (vm) {let cur = vm# 首先获取到报错的组件,之后递归查找当前组件的父组件,依次调用errorCaptured 方法。# 在遍历调用完所有 errorCaptured 方法、或 errorCaptured 方法有报错时,调用 globalHandleError 方法while ((cur = cur.$parent)) {const hooks = cur.$options.errorCaptured# 判断是否存在errorCaptured钩子函数if (hooks) {# 选项合并的策略,钩子函数会被保存在一个数组中for (let i = 0; i < hooks.length; i++) {# 如果errorCaptured 钩子执行自身抛出了错误,# 则用try{}catch{}捕获错误,将这个新错误和原本被捕获的错误都会发送给全局的config.errorHandler# 调用globalHandleError方法try {# 当前errorCaptured执行,根据返回是否是false值# 是false,capture = true,阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler# 是true capture = fale,组件的继承或父级从属链路中存在的多个 errorCaptured 钩子,会被相同的错误逐个唤起# 调用对应的钩子函数,处理错误const capture = hooks[i].call(cur, err, vm, info) === falseif (capture) return} catch (e) {globalHandleError(e, cur, 'errorCaptured hook')}}}}}# 除非禁止错误向上传播,否则都会调用全局的错误处理函数globalHandleError(err, vm, info)} finally {popTarget()}
}
# 异步错误处理函数
export function invokeWithErrorHandling (handler: Function,context: any,args: null | any[],vm: any,info: string
) {let restry {# 根据参数选择不同的handle执行方式res = args ? handler.apply(context, args) : handler.call(context)# handle返回结果存在# res._isVue an flag to avoid this being observed,如果传入值的_isVue为ture时(即传入的值是Vue实例本身)不会新建observer实例# isPromise(res) 判断val.then === 'function' && val.catch === 'function', val !=== null && val !== undefined# !res._handled _handle是Promise 实例的内部变量之一,默认是false,代表onFulfilled,onRejected是否被处理if (res && !res._isVue && isPromise(res) && !res._handled) {res.catch(e => handleError(e, vm, info + ` (Promise/async)`))# avoid catch triggering multiple times when nested calls# 避免嵌套调用时catch多次的触发res._handled = true}} catch (e) {# 处理执行错误handleError(e, vm, info)}return res
}#全局错误处理
function globalHandleError (err, vm, info) {# 获取全局配置,判断是否设置处理函数,默认undefined# 已配置if (config.errorHandler) {# try{}catch{} 住全局错误处理函数try {# 执行设置的全局错误处理函数,handle error 想干啥就干啥?return config.errorHandler.call(null, err, vm, info)} catch (e) {# 如果开发者在errorHandler函数中手动抛出同样错误信息throw err# 判断err信息是否相等,避免log两次# 如果抛出新的错误信息throw err Error('你好毒'),将会一起log输出if (e !== err) {logError(e, null, 'config.errorHandler')}}}# 未配置常规log输出logError(err, vm, info)
}# 错误输出函数
function logError (err, vm, info) {if (process.env.NODE_ENV !== 'production') {warn(`Error in ${info}: "${err.toString()}"`, vm)}/* istanbul ignore else */if ((inBrowser || inWeex) && typeof console !== 'undefined') {console.error(err)} else {throw err}
}
复制代码
欢乐时光
以上是本人对vue 错误处理的浅显理解,欢迎大家评论交流,共同进步, enjoy !
参考文档:
vue错误api
vue错误处理
Promise源码剖析
vue/issues/7074
转载于:https://juejin.im/post/5c8e139f6fb9a0710f47d949
浅出Vue 错误处理机制errorCaptured、errorHandler相关推荐
- Vue.js@2.6.10更新内置错误处机制,Fundebug同步支持相应错误监控
2019独角兽企业重金招聘Python工程师标准>>> 摘要: Fundebug 的 JavaScript 错误监控插件同步支持 Vue.js 异步错误监控. Vue.js 从诞生至 ...
- 浅入深出Vue:环境搭建
浅入深出Vue:环境搭建 工欲善其事必先利其器,该搭建我们的环境了. 安装NPM 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版本的NodeJS Windows安装程序 下载下来后,直 ...
- [科普]浅入浅出Liunx Shellcode
创建时间:2008-05-13 文章属性:原创 文章提交: pr0cess (pr0cess_at_cnbct.org) 浅入浅出Liunx Shellcode /*---------------- ...
- 浅入浅出深度学习理论实践
全文共9284个字,40张图,预计阅读时间30分钟. 前言 之前在知乎上看到这么一个问题:在实际业务里,在工作中有什么用得到深度学习的例子么?用到 GPU 了么?,回头看了一下自己写了这么多东西一直围 ...
- Python-Level1-day16:异常处理try-exceptraise语句,for迭代原理,深入手写创建迭代器;yield浅出使用生成器
作业 1. 三合一 2. 当天练习独立完成 3. 将员工管理系统分为4个模块employee_system.py 4. (选做)完成2048上下移动函数-- 自定义矩阵转置函数,实现行列颠倒-- ...
- Go语言的错误异常处理机制及其应用
一.背景 在日常编写golang程序或阅读别人的golang代码时,我们总会看到如下的一堆代码块: xx, err = func(xx) if err != nil {//do sth. to tac ...
- .net错误处理机制
.net错误处理机制 让我们想想,ASP.NET为我们提供了几种错误处理机制?如果同时使用他们是不是有一定的优先级?.NET提供了四种错误处理机制,它们有一定的优先级顺序:Page_Error事件&g ...
- 浅谈JavaScript错误
本文主要从前端开发者的角度谈一谈大多数前端开发者都会遇到的js错误,对错误产生的原因.发生阶段,以及如何应对错误进行分析.归纳和总结,希望得到一些有益的结论用来指导日常开发工作. 概念辨析 错误(Er ...
- golang错误处理机制(异常处理)
看一段代码,引入错误处理 对上面代码的总结: 在默认情况下,当发生错误后(panic) ,程序就会退出(崩溃.) 如果我们希望:当发生错误后,可以捕获到错误,并进行处理,保证程序可以继续执行.还可 以 ...
最新文章
- 《深入理解Nginx:模块开发与架构解析》一1.2 为什么选择Nginx
- python基础语法合集-python常用语法合集
- 001_Layout布局
- CSDN转载别人文章的详细步骤
- dosbox中的bebug指令
- 政策表达式截取json_json格式数据如何提取指定中文字符串。
- knn人脸识别判断_测试使用K-最近邻(kNN)算法的30个问题
- 如何让多文本内容只显示一行,其余用省略号来显示
- 可达龙博客的第一篇文
- 二维数组各行求和_JS数组reduce()方法详解及高级技巧
- 用R语言实现信息度量
- Django项目详解2——动态响应的web应用
- 优化计算机组策略,Windows 10神州网信版优化
- 怎样修改计算机用户文件名,win10修改用用户文件夹名字怎么操作_win10更改用户文件夹名称方法...
- 二叉树的性质及其创建
- 如何才能成为数字IC后端ECO专家?
- 37互娱java待遇,37互娱现场java一面
- 苹果6s出现连接不上服务器未响应,苹果6s的蜂窝移动数据打开没反应怎么办
- 现在有多少老婆不上班,全靠男人一个人赚钱养家的,过得怎么样?
- 鼻炎舒宁治过敏性鼻炎
热门文章
- Spark源码系列(四)图解作业生命周期
- “Could not change executable permissions on the application”的原因和解决方法
- shell 将两行内容合并到同一行
- 【PetShop 4.0学习】4.数据库结构
- Your password has expired. To log in you must change it using a client that supports expired pass...
- ceph rbd resize之后文件系统的调节
- Java可变参数 Python可变参数 Scala可变参数
- Macaca基础原理解析
- 河神,不用砍死那个天秤座的男孩了
- 如何提高PHP代码的质量?第一部分 自动化工具