網(wǎng)站首頁 Vue 正文
主題
在 vue2.6.x 及之后版本中(僅限于此API未被毀滅性更新前)使用全局 errorHandler 鉤子來進(jìn)行 vue 組件中所拋錯(cuò)誤的捕捉與處理。
現(xiàn)狀
vue2.6 之前,errorHandler 只能捕捉同步函數(shù)拋出的錯(cuò)誤,而在實(shí)際開發(fā)中我們關(guān)心得更多的是調(diào)用接口時(shí)可能拋出的錯(cuò)誤,ES7之后通常使用 async await 的方式進(jìn)行接口調(diào)用,對于async函數(shù)中拋出的錯(cuò)誤errorHandler并不能捕捉到。因此我們使用了裝飾器(Decorator)進(jìn)行錯(cuò)誤捕捉,方法可行,癢點(diǎn)在于需要在很多個(gè)組件中引入裝飾器,然后放置在每一個(gè)需要的位置(還有個(gè)近乎絕癥的“痛點(diǎn)”是 vetur 插件對“不規(guī)范使用decorator”的紅色警告)。
當(dāng)前使用示例(盡可能簡化版):
// errorConfigs.js
import { debounce } from 'lodash';
const DEBOUNCE_TIME = 500;
const errorProcessorConfigs = [{
assert (error) {
return ErrorAssert.isUserInfoNotExist(error); // ErrorAssert為內(nèi)部Error斷言庫,使用了webpack的ProvidePlugin聲明
},
processor: debounce(() => alert('用戶信息不存在'), DEBOUNCE_TIME)
}, {
assert (error) {
return ErrorAssert.isAppInfoNotExist(error);
},
processor: debounce(() => alert('應(yīng)用信息不存在'), DEBOUNCE_TIME)
}]
// errorProcessor.js
import errorProcessorConfigs from '@src/configs/errorConfigs';
function errorProcessor(error) {
let errorProcessorConfig = errorProcessorConfigs.find(config => config.assert(error));
if (errorProcessorConfig !== undefined) {
errorProcessorConfig.processor(error);
}
throw error; // 處理完之后繼續(xù)將錯(cuò)誤拋出以中斷程序流程
};
export default errorProcessor;
// errorCatcher.js
import errorProcessor from './errorProcessor';
function errorCatcher(target, name, descriptor) {
const originFunc = descriptor.value;
descriptor.value = async function () {
try {
return await originFunc.apply(this, arguments);
} catch (error) {
return errorProcessor(error);
}
};
return descriptor;
};
export default errorCatcher;
// xxx.vue
/* template */
<script>
import errorCatcher from '@services/errorCatcher';
import checkLogin from '@services/checkLogin';
import resources from '@services/resources';
export default {
@errorCatcher
async created () {
await checkLogin();
this.fetchUserInfo();
},
methods: {
@errorCatcher
async fetchUserInfo () {
const userInfo = await resources.user.fetch();
// ...
},
}
};
</script>
/* style */
可行性
官網(wǎng)說明:
從 2.6.0 起,這個(gè)鉤子也會(huì)捕獲 v-on DOM 監(jiān)聽器內(nèi)部拋出的錯(cuò)誤。另外,如果任何被覆蓋的鉤子或處理函數(shù)返回一個(gè) Promise 鏈 (例如 async 函數(shù)),則來自其 Promise 鏈的錯(cuò)誤也會(huì)被處理。
測試:
// main.js
/* ... */
Vue.config.errorHandler = function (err, vm, info) {
console.error('error---', err)
console.info('vm---', vm)
console.info('info---', info)
}
/* ... */
// Home.vue
/* template */
<script>
export default {
async created () {
const error = new Error('test error');
error.code = -1;
throw error;
}
}
</script>
/* style */
console:
應(yīng)用
// main.js
import Vue from 'vue';
import errorProcessor from '@services/errorProcessor';
Vue.config.errorHandler = errorProcessor;
/* ... */
// xxx.vue
/* template */
<script>
import checkLogin from '@services/checkLogin';
import resources from '@services/resources';
export default {
async created () {
await checkLogin();
this.fetchUserInfo();
},
methods: {
async fetchUserInfo () {
const userInfo = await resources.user.fetch();
// ...
},
}
};
</script>
/* style */
對比
裝飾器 | errorHandler | |
---|---|---|
優(yōu)勢 | 1.使用靈活,可多個(gè)裝飾器組裝使用;2.裝飾器可以接收參數(shù),進(jìn)行更高階的應(yīng)用; | 1.全局設(shè)置,一處設(shè)置處處受益,使用較為簡潔;2. 可以直接拿到 this,獲取更多信息,進(jìn)行更多操作;3. info 可輔助定位錯(cuò)誤源; |
劣勢 | 1.在每一個(gè)需要的函數(shù)處都需要使用裝飾器進(jìn)行包裝,組件中也需要引入裝飾器模塊;2.裝飾器被babel編譯后細(xì)微的增加文件體積;3.編譯期生效,因此如果 errorProcessorConfigs想引入 router 就需要進(jìn)行一些特殊處理(如將routes 配置放在 main.js 中添加,或者通過變量方式傳入) | 1.無法向錯(cuò)誤處理中傳入?yún)?shù);2.全局只能有一個(gè),如果想針對不同場景下拋出的同一類 error 進(jìn)行不同處理,則需要加入判斷邏輯,影響函數(shù)純粹性。3.捕捉錯(cuò)誤條件限制于同步函數(shù)或函數(shù)返回promise鏈。4.watch中調(diào)用的異步函數(shù)暫時(shí)無法被捕捉 |
總結(jié)
裝飾器錯(cuò)誤處理方式略顯繁重,但并不會(huì)被errorHandler完全取締,如果想讓errorHandler盡可能的捕捉到出現(xiàn)的錯(cuò)誤,則可能需要對代碼進(jìn)行一些更為嚴(yán)格的調(diào)整(構(gòu)建promise鏈),可以根據(jù)實(shí)際的場景,將二者結(jié)合使用,以產(chǎn)生更大的受益(舉個(gè)例子:某些場景下的錯(cuò)誤可以使用裝飾器處理并吞掉,不走全局處理)。
期待提建議和補(bǔ)充·~·
原文鏈接:https://blog.csdn.net/qq_39300332/article/details/87926877
相關(guān)推薦
- 2023-04-03 Python數(shù)據(jù)結(jié)構(gòu)棧實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換簡單示例_python
- 2022-06-19 C#中的checksum計(jì)算公式_C#教程
- 2022-09-24 教你創(chuàng)建一個(gè)帶診斷工具的.NET鏡像_C#教程
- 2022-08-20 Django細(xì)致講解多對多使用through自定義中間表方法_python
- 2022-02-01 nginx 上傳圖片出現(xiàn)跨域
- 2022-12-21 Python?threading中l(wèi)ock的使用詳解_python
- 2022-05-13 類實(shí)例化 對象的內(nèi)存模型 及 內(nèi)存占用分析
- 2022-09-13 C++中的偽隨機(jī)數(shù)_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支