在前端應用程序中,最常見的錯誤/異常類型可能包括以下幾種:
- 語法錯誤:使用了一些錯誤的語法
- 運行時錯誤:由於執行期間的非法操作導致的
- 邏輯錯誤:由於程序邏輯錯誤
- Http 錯誤:API 返回的錯誤
有很多方法可以解決上面的問題,例如使用 eslint
來檢查語法錯誤,使用適當的 try-catch
語句處理運行時錯誤,通過適當的單頁或者集成測試減少邏輯錯誤,http
錯誤可以通過使用 Promise
來處理。
全局配置
Vue 應用程序有一個全局配置 Vue.config
,可以配置禁止日志和告警、devtools、錯誤處理程序等等。
可以用自己的配置覆蓋這些配置,對於錯誤處理,可以為其分配一個處理函數 Vue.config.errorHandler
。在整個應用程序中,任何 Vue實例(Vue組件)中的任何未捕獲異常都會調用該處理程序。以下代碼片段為Vue 應用程序注冊一個錯誤處理方法(一般在項目的 main.js
文件中):
/** * * @param {*} error 錯誤跟蹤 * @param {*} vm 組件錯誤 * @param {*} info 特定的錯誤信息,如生命周期鈎子、事件等。 */ Vue.config.errorHandler = (error, vm, info) => { console.info(error); console.info(vm); console.info(info); };
處理程序包含 3 個參數:
error
:完整的錯誤跟蹤,包含message
和error stack
vm
:發生錯誤的Vue組件/實例info
: 特定的錯誤信息,例如生命周期鈎子、事件等。
Vue.config.errorHandler
捕獲特定於Vue實例的錯誤,但無法捕獲 Vue 實例之外的錯誤,如服務。
要捕獲 Vue 實例之外的錯誤,可以使用 window.onerror
事件,可以注冊一個錯誤處理函數,該函數將捕獲所有非特定於 Vue 實例的未處理異常。下面的代碼片段為其應用注冊window.onerror
異常處理函數:
window.onerror = function(message, source, lineno, colno, error) { // TODO: 定義跟蹤邏輯 };
自定義異常組件
通常項目中有一些可預知的異常需要自定義 UI ,可以自定義異常組件來統一接管異常的處理。實現的邏輯是如果有異常顯示異常信息,否則就顯示組件信息,代碼如下:
<template> <div> <slot v-if="errors" name="errors"> <a-alert :message="errors.title" :description="errors.description" show-icon type="warning" class="mb-2" > </a-alert> </slot> <slot v-else></slot> </div> </template> <script> export default { name: "QtErrorContainer", props: { errors: Object, // {title:"500錯誤",description:"數據庫連接超時"} }, }; </script>
以上面的組件作為容器來加載其他組件,如通過后台接口拉取列表數據,調用如下:
<QtErrorContainer :errors="errors"> <a-table ></a-table> </QtErrorContainer>
上面的代碼在 errors
為 null
或者 false
的時候,顯示表格組件 <a-table></a-table>
,否則不顯示而顯示異常信息。這樣實現好處就是所有可預知的異常都由統一的組件來處理,提高復用和靈活性。
日志處理
對於日志處理,可以封裝為一個獨立的類,如 logger
,負責收集Vue中所有的異常日志,輸出到控制台或者通過接口發送到服務器存儲或借助第三方日志跟蹤平台,只需要修改 logger
的處理方式即可,如下:
import { environment } from "@/environment/"; /** * Logger 日志類 */ class Logger { /** * @constructor AppLogger */ constructor() { this.init(); } init() { if (environment !== "production") { this.log = console.log.bind(console); this.debug = console.debug.bind(console); this.info = console.info.bind(console); this.warn = console.warn.bind(console); this.error = console.error.bind(console); this.toServer = this.error; } else { /** 在生產的情況下,替換函數定義 */ this.log = this.debug = this.info = this.warn = this.error = () => {}; /** TODO: 方法中可以增加接口或者第三方平台跟蹤的邏輯 */ this.toServer = (err) => { console.error(err); }; } } } const logger = new Logger(); export { logger };
可以將 logger
類引用到上面的全局配置的處理方法中,如下:
mport Vue from "vue"; import { logger } from "@/logger"; /** * * @param {*} error 錯誤跟蹤 * @param {*} vm 組件錯誤 * @param {*} info 特定的錯誤信息,如生命周期鈎子、事件等。 */ Vue.config.errorHandler = (error, vm, info) => { logger.toServer({ error, vm, info }); }; window.onerror = function (message, source, lineno, colno, error) { logger.toServer({ message, source, lineno, colno, error }); };
總結
錯誤處理對於應用程序非常重要,在本文中,討論了Vue.config.errorHandler
使用生命周期鈎子的全局錯誤處理程序和自定義組件來處理可預知的異常。本文提供了基本細節,借助這些細節,可以輕松實現應用程序的錯誤處理並記錄它們,這將有助於創建更好的用戶體驗。