日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 Vue 正文

vue.config.errorHandler 錯誤處理調研

作者:Mr.Cool 更新時間: 2022-04-04 Vue

主題

在 vue2.6.x 及之后版本中(僅限于此API未被毀滅性更新前)使用全局 errorHandler 鉤子來進行 vue 組件中所拋錯誤的捕捉與處理。

現狀

vue2.6 之前,errorHandler 只能捕捉同步函數拋出的錯誤,而在實際開發中我們關心得更多的是調用接口時可能拋出的錯誤,ES7之后通常使用 async await 的方式進行接口調用,對于async函數中拋出的錯誤errorHandler并不能捕捉到。因此我們使用了裝飾器(Decorator)進行錯誤捕捉,方法可行,癢點在于需要在很多個組件中引入裝飾器,然后放置在每一個需要的位置(還有個近乎絕癥的“痛點”是 vetur 插件對“不規范使用decorator”的紅色警告)。

當前使用示例(盡可能簡化版):

// errorConfigs.js
import { debounce } from 'lodash';
 
 
const DEBOUNCE_TIME = 500;
const errorProcessorConfigs = [{
  assert (error) {
    return ErrorAssert.isUserInfoNotExist(error); // ErrorAssert為內部Error斷言庫,使用了webpack的ProvidePlugin聲明
  },
  processor: debounce(() => alert('用戶信息不存在'), DEBOUNCE_TIME)
}, {
  assert (error) {
    return ErrorAssert.isAppInfoNotExist(error);
  },
  processor: debounce(() => alert('應用信息不存在'), 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; // 處理完之后繼續將錯誤拋出以中斷程序流程
};
 
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 */

可行性

官網說明:
從 2.6.0 起,這個鉤子也會捕獲 v-on DOM 監聽器內部拋出的錯誤。另外,如果任何被覆蓋的鉤子或處理函數返回一個 Promise 鏈 (例如 async 函數),則來自其 Promise 鏈的錯誤也會被處理。
測試:

// 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:
在這里插入圖片描述

應用

// 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
優勢 1.使用靈活,可多個裝飾器組裝使用;2.裝飾器可以接收參數,進行更高階的應用; 1.全局設置,一處設置處處受益,使用較為簡潔;2. 可以直接拿到 this,獲取更多信息,進行更多操作;3. info 可輔助定位錯誤源;
劣勢 1.在每一個需要的函數處都需要使用裝飾器進行包裝,組件中也需要引入裝飾器模塊;2.裝飾器被babel編譯后細微的增加文件體積;3.編譯期生效,因此如果 errorProcessorConfigs想引入 router 就需要進行一些特殊處理(如將routes 配置放在 main.js 中添加,或者通過變量方式傳入) 1.無法向錯誤處理中傳入參數;2.全局只能有一個,如果想針對不同場景下拋出的同一類 error 進行不同處理,則需要加入判斷邏輯,影響函數純粹性。3.捕捉錯誤條件限制于同步函數或函數返回promise鏈。4.watch中調用的異步函數暫時無法被捕捉

總結

裝飾器錯誤處理方式略顯繁重,但并不會被errorHandler完全取締,如果想讓errorHandler盡可能的捕捉到出現的錯誤,則可能需要對代碼進行一些更為嚴格的調整(構建promise鏈),可以根據實際的場景,將二者結合使用,以產生更大的受益(舉個例子:某些場景下的錯誤可以使用裝飾器處理并吞掉,不走全局處理)。

期待提建議和補充·~·

原文鏈接:https://blog.csdn.net/qq_39300332/article/details/87926877

欄目分類
最近更新