Vue全局監(jiān)測錯(cuò)誤生成錯(cuò)誤日志過程
前言
在做完一個(gè)項(xiàng)目后,之后的維護(hù)尤為重要。
這時(shí),如果項(xiàng)目配置了錯(cuò)誤日志記錄,這樣能大大減少維護(hù)難度。雖然不一定能捕獲到全部的錯(cuò)誤,但是一般的錯(cuò)誤還是可以監(jiān)測到的。
這樣就不用測試人員去一遍一遍復(fù)現(xiàn)bug了。
一、準(zhǔn)備工作
(1)規(guī)定錯(cuò)誤碼
像是請(qǐng)求碼(404、500)一樣,我覺得錯(cuò)誤都應(yīng)該規(guī)定好對(duì)應(yīng)的錯(cuò)誤碼。個(gè)人喜好。
// 錯(cuò)誤代碼 const errCode = new Map([ // 本地系統(tǒng)錯(cuò)誤 ['E1001', '系統(tǒng)未知錯(cuò)誤'], ['E1002', 'vue邏輯錯(cuò)誤'], ['E1003', 'JavaScript錯(cuò)誤'], ['E1004', '靜態(tài)資源加載錯(cuò)誤'], ['E1005', '請(qǐng)求錯(cuò)誤'], ['E1006', 'Promise錯(cuò)誤'] ])
(2)設(shè)置錯(cuò)誤處理函數(shù)
每個(gè)項(xiàng)目對(duì)于錯(cuò)誤的處理不一樣,我這邊就不寫邏輯了。只做了保存日志。
這里導(dǎo)出處理函數(shù)是為了手動(dòng)處理請(qǐng)求錯(cuò)誤以及Promise.catch()中的錯(cuò)誤
// 錯(cuò)誤處理函數(shù)
export const errorHandler = (code: string, msg: string, file = 'null') => {
// 這里處理監(jiān)聽到的錯(cuò)誤
// 保存錯(cuò)誤信息
saveLog({ code: code, type: errCode.get(`$[code]`), msg: msg, router: router.currentRoute.value.fullPath, file: file, createTime: new Date().toLocaleString() })
}
(3)保存錯(cuò)誤日志
演示保存到 localStorage中,并且只存50條,超過則把最舊的刪除
type errorParams = {
code: string // 錯(cuò)誤代碼
msg: string // 錯(cuò)誤內(nèi)容
router: string // 錯(cuò)誤路由地址
file?: string // 錯(cuò)誤的文件(不一定有)
createTime: string // 發(fā)現(xiàn)錯(cuò)誤的時(shí)間
type?: string // 錯(cuò)誤的類型
}
// localstorage 保存錯(cuò)誤信息 最多50條避免爆滿
const saveLog = (data: errorParams): void => {
const nowData = localStorage.getItem('ERROR')
if (nowData) {
const allData = JSON.parse(nowData)
sortArray(allData)
// 只存50條錯(cuò)誤信息
if (allData.length > 50) {
// 已存50條
allData[0] = data
sortArray(allData)
} else {
allData.push(data)
}
localStorage.setItem('ERROR', JSON.stringify(allData))
} else {
localStorage.setItem('ERROR', JSON.stringify([data]))
}
}
二、監(jiān)聽錯(cuò)誤
項(xiàng)目上線后出現(xiàn)的錯(cuò)誤一般有四種,JS錯(cuò)誤、靜態(tài)資源錯(cuò)誤、vue邏輯錯(cuò)誤、請(qǐng)求錯(cuò)誤。其他的錯(cuò)誤一般在編寫階段已經(jīng)提示了?;旧现槐O(jiān)聽這四種就能包含項(xiàng)目上線后可能出現(xiàn)的錯(cuò)誤了。
(1)JS錯(cuò)誤與靜態(tài)資源加載錯(cuò)誤
例子:數(shù)組或者對(duì)象不存在某個(gè)值等等。這里我統(tǒng)稱JS錯(cuò)誤了。
監(jiān)聽方法如下:
window.addEventListener('error', (error: any) => {
// 區(qū)分是否是js錯(cuò)誤
if (error.message) {
console.error('監(jiān)測到E1003錯(cuò)誤');
errorHandler('E1003', error.message, error.filename)
} else {
console.error('監(jiān)測到E1004錯(cuò)誤');
errorHandler('E1004', error.target.currentSrc, error.filename)
}
}, true)
(2)Vue邏輯錯(cuò)誤
vue官方提供了一個(gè)能監(jiān)測組件渲染方法執(zhí)行期間及偵 聽 器拋出的未捕獲錯(cuò)誤的方法 app.config.errorHandler,app是main.ts中的app。
// vue渲染或者vue處理錯(cuò)誤
app.config.errorHandler = (err: any) => {
console.error('監(jiān)測到E1002錯(cuò)誤');
console.error(err);
errorHandler('E1002', err.name + ':' + err.message)
}
(3)請(qǐng)求錯(cuò)誤與Promise錯(cuò)誤
這兩種錯(cuò)誤本身有自己的監(jiān)聽函數(shù),所以只需要在監(jiān)聽到錯(cuò)誤后調(diào)用之前導(dǎo)出的錯(cuò)誤處理函數(shù)即可。
請(qǐng)求錯(cuò)誤:在響應(yīng)攔截器中(axios.interceptors.response) 中寫邏輯調(diào)用錯(cuò)誤處理函數(shù)即可
Promise:在catch中調(diào)用錯(cuò)誤處理函數(shù)即可
三、效果演示
隨便寫了個(gè)表格

四、完整代碼
使用方法:
// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { watchError } from './utils/watchError'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
// 如果沒有app,自己用個(gè)變量等于createApp即可
watchError(app)
Promise.catch()與請(qǐng)求響應(yīng)器直接使用errorHandler
import { errorHandler } from '../utils/watchError'
errorHandler('E1006', '測試Promise錯(cuò)誤')
errorHandler('E1005', `請(qǐng)求地址:${error.config.method}:${error.config.baseURL}/${error.config.url}`)
監(jiān)聽函數(shù):
// src/utils/watchError.ts
import router from '@/router/index'
// 錯(cuò)誤代碼
const errCode = new Map([
// 本地系統(tǒng)錯(cuò)誤
['E1001', '系統(tǒng)未知錯(cuò)誤'],
['E1002', 'vue邏輯錯(cuò)誤'],
['E1003', 'JavaScript錯(cuò)誤'],
['E1004', '靜態(tài)資源加載錯(cuò)誤'],
['E1005', '請(qǐng)求錯(cuò)誤'],
['E1006', 'Promise錯(cuò)誤']
])
// 開啟監(jiān)聽
export const watchError = (app: any) => {
// vue渲染或者vue處理錯(cuò)誤
app.config.errorHandler = (err: any) => {
console.error('監(jiān)測到E1002錯(cuò)誤');
console.error(err.filename);
errorHandler('E1002', err.name + ':' + err.message)
}
// 靜態(tài)資源加載錯(cuò)誤 或者 JS錯(cuò)誤
window.addEventListener('error', (error: any) => {
// 區(qū)分是否是js錯(cuò)誤
if (error.message) {
console.error('監(jiān)測到E1003錯(cuò)誤');
errorHandler('E1003', error.message, error.filename)
} else {
console.error('監(jiān)測到E1004錯(cuò)誤');
errorHandler('E1004', error.target.currentSrc, error.filename)
}
}, true)
}
// 錯(cuò)誤處理函數(shù)
export const errorHandler = (code: string, msg: string, file = 'null') => {
// 這里處理監(jiān)聽到的錯(cuò)誤
// 保存錯(cuò)誤信息
saveLog({ code: code, type: errCode.get(`$[code]`), msg: msg, router: router.currentRoute.value.fullPath, file: file, createTime: new Date().toLocaleString() })
}
type errorParams = {
code: string // 錯(cuò)誤代碼
msg: string // 錯(cuò)誤內(nèi)容
router: string // 錯(cuò)誤路由地址(根據(jù)hash地址‘/#/'切割而來,具體看需求)
file?: string // 錯(cuò)誤的文件(不一定有)
createTime: string // 發(fā)現(xiàn)錯(cuò)誤的時(shí)間
type?: string // 錯(cuò)誤的類型
}
// localstorage 保存錯(cuò)誤信息 最多50條避免爆滿
const saveLog = (data: errorParams): void => {
const nowData = localStorage.getItem('ERROR')
if (nowData) {
const allData = JSON.parse(nowData)
sortArray(allData)
// 只存50條錯(cuò)誤信息
if (allData.length > 50) {
// 已存50條
allData[0] = data
sortArray(allData)
} else {
allData.push(data)
}
localStorage.setItem('ERROR', JSON.stringify(allData))
} else {
localStorage.setItem('ERROR', JSON.stringify([data]))
}
}
// 錯(cuò)誤日志排序
const sortArray = (allData: string[]) => {
allData.sort((a: any, b: any) => {
if (a.createTime > b.createTime) {
return 1
}
return -1
})
}
五、總結(jié)
水平有限,主要是針對(duì)我自己的項(xiàng)目所做的處理,如果需要更多的信息,也可以在error對(duì)象中獲取到。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue中使用echarts實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)綁定以及獲取后端接口數(shù)據(jù)
總結(jié)一下自己最近項(xiàng)目中用echarts動(dòng)態(tài)獲取接口數(shù)據(jù)并畫圖的方法,下面這篇文章主要給大家介紹了關(guān)于vue中使用echarts實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)綁定以及獲取后端接口數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2022-07-07
Vue2.0父組件與子組件之間的事件發(fā)射與接收實(shí)例代碼
這篇文章主要介紹了Vue2.0父組件與子組件之間的事件發(fā)射與接收實(shí)例代碼,需要的朋友可以參考下2017-09-09
Vertx基于EventBus發(fā)送接受自定義對(duì)象
這篇文章主要介紹了Vertx基于EventBus發(fā)送接受自定義對(duì)象,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
Vue2.0基于vue-cli+webpack Vuex的用法(實(shí)例講解)
下面小編就為大家?guī)硪黄猇ue2.0基于vue-cli+webpack Vuex的用法(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09
把vue-router和express項(xiàng)目部署到服務(wù)器的方法
下面小編就為大家分享一篇把vue-router和express項(xiàng)目部署到服務(wù)器的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-02-02
Element的el-tree控件后臺(tái)數(shù)據(jù)結(jié)構(gòu)的生成以及方法的抽取
這篇文章主要介紹了Element的el-tree控件后臺(tái)數(shù)據(jù)結(jié)構(gòu)的生成以及方法的抽取,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

