跨平台应用开发进阶(十八) :全局异常日志处理方案探究

一、前言

众所周知,Vue有一个配置Vue.config.errorHandler,用于指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。可以借助这个函数,进行应用的错误日志记录并做一些自定义的处理,防止出现一些严重异常导致应用挂掉。

一般情况下错误日志可以在前端页面中展示,并且需要记录到数据库中。在异常发生时可以调用后台接口存储到后台,前端查询的实现可以使用状态管理(如果需要持久化存储就配合本地存储,但一般不太建议,因为异常太多的话会影响性能)

二、代码实现

可以通过插件形式实现全局异常处理函数,并挂载到Vue.config.errorHandler上。

首先,配置一个开关,用于控制在开发环境还是生产环境中启用日志。

settings.js

java 复制代码
export default {
    /**
	 * @type {string | array} 'production' | ['production', 'development']
	 * @description 在什么环境中记录日志,生产环境还是开发环境
	 * 默认生产环境写入错误日志,避免在开发环境调试期间错误日志过多且影响性能
	 * 如果需要在开发环境中记录错误日志,可以修改为 ['production', 'development']
	 */
	errorLog: ['production', 'development']
}

然后,准备一个状态管理相关文件,用于记录日志。

errorLog.js

java 复制代码
const state = {
	logs: []
}
 
const mutations = {
	ADD_ERROR_LOG: (state, log) => {
		state.logs.push(log)
	},
	CLEAR_ERROR_LOG: (state) => {
		state.logs.splice(0)
	}
}
 
const actions = { 
	addErrorLog({
		commit
	}, log) {
		commit('ADD_ERROR_LOG', log)
	},
	clearErrorLog({
		commit
	}) {
		commit('CLEAR_ERROR_LOG')
	}
}
 
export default {
	namespaced: true,
	state,
	mutations,
	actions
}

store/index.js中引入errorLog模块

store/index.js

java 复制代码
import Vue from 'vue'
import Vuex from 'vuex'
import errorLog from './modules/errorLog'
 
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
 
export default new Vuex.Store({
	modules: {
		errorLog 
	},
	// 在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
	strict: debug
})

然后写一个插件,将全局异常处理函数挂载在Vue.config.errorHandler上。

utils/error-log.js

java 复制代码
import store from '@/store'
import {
	isString,
	isArray
} from './util'
 
import config from '@/setting'
 
const install = function (Vue) {
	const {
		errorLog: needErrorLog
	} = config;
	
	function checkNeed() {
		const env = process.env.NODE_ENV;
		
		if (isString(needErrorLog)) {
			return env === needErrorLog
		}
		
		if (isArray(needErrorLog)) {
			return needErrorLog.includes(env)
		}
		
		return false
	}
	
	function writeErrorLog({
		err,
		route
	}) {
		// ajax 调用后台接口去记录日志
	}
	
	function errorHandler(err, vm, info, a) {
		// route: uni-app路由,这里可以修改成自己的内容或去掉
		let pages = getCurrentPages(),
			route = '';
		if (pages.length) {
			route = pages[pages.length - 1].route;
		}
		console.error('globalError', err);
		vm && console.error('globalError-vm', vm);
		info && console.error(info);
		route && console.error('page', route); // route: uni-app路由,这里可以修改成自己的内容或去掉
		
		if (checkNeed()) {
			// Don't ask me why I use Vue.nextTick, it just a hack.
			// detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
			Vue.nextTick(() => {
				store.dispatch('errorLog/addErrorLog', {
					err,
					info,
					route // route:uni-app路由,这里可以修改成自己的内容或去掉
				})
				
				writeErrorLog({
					err,
					info,
					route // route:uni-app路由,这里可以修改成自己的内容或去掉
				})
			})
		}
	}
	
	// 挂载在原型上,即可以在其他页面中使用this.$throw
	Vue.prototype.$throw = errorHandler
	Vue.config.errorHandler = errorHandler
}
 
export default install;

至此,已经实现了全局的错误拦截和状态记录。

三、uni-app优化

如果是uni-app项目,也可以在App.vue中定义生命周期钩子onError执行$thow,这样也能触发全局的错误处理函数。 App.vue

java 复制代码
export default {
	onLaunch() {
		console.log('App-Launch');
	},
 
	onShow() {
		console.log('App Show');
	},
 
	onHide() {
		console.log('App Hide')
	},
 
	onError(err) {
		this.$throw(err);
	}
}

也可以在页面中使用errorCaptured捕获页面中发生的异常。

java 复制代码
errorCaptured (err: Error, vm: Component, info: string) => ?boolean

当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象发生错误的组件实例 以及一个包含错误来源信息的字符串 。此钩子可以返回 false 以阻止该错误继续向上传播。

java 复制代码
// 当捕获一个来自子孙组件的错误时被调用
errorCaptured(err, vm, info) {
    // 页面级异常处理    
	return false // 全局的config.errorHandler将无法捕获到这里的异常
}

四、拓展阅读

相关推荐
崔庆才丨静觅14 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606114 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了15 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅15 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅15 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅15 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment15 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅16 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊16 小时前
jwt介绍
前端
爱敲代码的小鱼16 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax