一種Vue應用程序錯誤/異常處理機制

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在構建前端應用程序不像以前那麼簡單,現在,應用程序更加複雜和多樣。這就需要在構建前端應用程序的時候考慮很多,錯誤/異常處理是最重要的方面之一。在應用程序中擁有良好的錯誤處理機制可以帶來很多的好處,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"良好的錯誤處理機制可以避免應用程序在出現未處理的異常時崩潰","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在生產環境下,可以輕鬆地存儲或者跟蹤錯誤記錄日誌,以便異常的處理","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以統一處理錯誤信息,例如在不破壞應用程序交互的情況下,更改錯誤信息展示UI","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有助於改善用戶體驗","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在前端應用程序中,最常見的錯誤/異常類型可能包括以下幾種:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"語法錯誤","attrs":{}},{"type":"text","text":":使用了一些錯誤的語法","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"運行時錯誤","attrs":{}},{"type":"text","text":":由於執行期間的非法操作導致的","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"邏輯錯誤","attrs":{}},{"type":"text","text":":由於程序邏輯錯誤","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Http 錯誤","attrs":{}},{"type":"text","text":":API 返回的錯誤","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有很多方法可以解決上面的問題,例如使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"eslint","attrs":{}}],"attrs":{}},{"type":"text","text":" 來檢查語法錯誤,使用適當的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"try-catch","attrs":{}}],"attrs":{}},{"type":"text","text":" 語句處理運行時錯誤,通過適當的","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"單頁或者集成","attrs":{}},{"type":"text","text":"測試減少邏輯錯誤,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http","attrs":{}}],"attrs":{}},{"type":"text","text":" 錯誤可以通過使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Promise","attrs":{}}],"attrs":{}},{"type":"text","text":" 來處理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之前在文章《","attrs":{}},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/d3d8c7e76e2b686169f90b534","title":"","type":null},"content":[{"type":"text","text":"淺談前端異常監控平臺實現方案","attrs":{}}]},{"type":"text","text":"》中簡單介紹前端異常監控的實現方案,在本文中,將推薦一種在 Vue 應用程序中實現","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"錯誤/異常","attrs":{}},{"type":"text","text":"處理機制。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"全局配置","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Vue 應用程序有一個全局配置 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue.config","attrs":{}}],"attrs":{}},{"type":"text","text":",可以配置禁止日誌和告警、devtools、錯誤處理程序等等。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以用自己的配置覆蓋這些配置,對於錯誤處理,可以爲其分配一個處理函數 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue.config.errorHandler","attrs":{}}],"attrs":{}},{"type":"text","text":"。在整個應用程序中,任何 Vue實例(Vue組件)中的任何未捕獲異常都會調用該處理程序。以下代碼片段爲Vue 應用程序註冊一個錯誤處理方法(一般在項目的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"main.js","attrs":{}}],"attrs":{}},{"type":"text","text":" 文件中):","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"/**\n *\n * @param {*} error 錯誤跟蹤\n * @param {*} vm 組件錯誤\n * @param {*} info 特定的錯誤信息,如生命週期鉤子、事件等。\n */\nVue.config.errorHandler = (error, vm, info) => {\n console.info(error);\n console.info(vm);\n console.info(info);\n};\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"處理程序包含 3 個參數:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"error","attrs":{}}],"attrs":{}},{"type":"text","text":":完整的錯誤跟蹤,包含 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"message","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"error stack","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"vm","attrs":{}}],"attrs":{}},{"type":"text","text":":發生錯誤的Vue組件/實例","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"info","attrs":{}}],"attrs":{}},{"type":"text","text":": 特定的錯誤信息,例如生命週期鉤子、事件等。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Vue.config.errorHandler","attrs":{}}],"attrs":{}},{"type":"text","text":" 捕獲特定於Vue實例的錯誤,但無法捕獲 Vue 實例之外的錯誤,如服務。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要捕獲 Vue 實例之外的錯誤,可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"window.onerror","attrs":{}}],"attrs":{}},{"type":"text","text":" 事件,可以註冊一個錯誤處理函數,該函數將捕獲所有非特定於 Vue 實例的未處理異常。下面的代碼片段爲其應用註冊","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"window.onerror","attrs":{}}],"attrs":{}},{"type":"text","text":" 異常處理函數:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"window.onerror = function(message, source, lineno, colno, error) {\n // TODO: 定義跟蹤邏輯\n};\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"自定義異常組件","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常項目中有一些可預知的異常需要自定義 UI ,可以自定義異常組件來統一接管異常的處理。實現的邏輯是如果有異常顯示異常信息,否則就顯示組件信息,代碼如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n\n\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上面的組件作爲容器來加載其他組件,如通過後臺接口拉取列表數據,調用如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n \n\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面的代碼在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"errors","attrs":{}}],"attrs":{}},{"type":"text","text":" 爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"null","attrs":{}}],"attrs":{}},{"type":"text","text":" 或者 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"false","attrs":{}}],"attrs":{}},{"type":"text","text":" 的時候,顯示錶格組件 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"","attrs":{}}],"attrs":{}},{"type":"text","text":",否則不顯示而顯示異常信息。這樣實現好處就是所有可預知的異常都由統一的組件來處理,提高複用和靈活性。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"日誌處理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於日誌處理,可以封裝爲一個獨立的類,如 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"logger","attrs":{}}],"attrs":{}},{"type":"text","text":" ,負責收集Vue中所有的異常日誌,輸出到控制檯或者通過接口發送到服務器存儲或藉助第三方日誌跟蹤平臺,只需要修改 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"logger","attrs":{}}],"attrs":{}},{"type":"text","text":" 的處理方式即可,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"import { environment } from \"@/environment/\";\n\n/**\n * Logger 日誌類\n */\nclass Logger {\n /**\n * @constructor AppLogger\n */\n constructor() {\n this.init();\n }\n\n init() {\n if (environment !== \"production\") {\n this.log = console.log.bind(console);\n this.debug = console.debug.bind(console);\n this.info = console.info.bind(console);\n this.warn = console.warn.bind(console);\n this.error = console.error.bind(console);\n this.toServer = this.error;\n } else {\n /** 在生產的情況下,替換函數定義 */\n this.log = this.debug = this.info = this.warn = this.error = () => {};\n /** TODO: 方法中可以增加接口或者第三方平臺跟蹤的邏輯 */\n this.toServer = (err) => {\n console.error(err);\n };\n }\n }\n}\n\nconst logger = new Logger();\n\nexport { logger };\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以將 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"logger","attrs":{}}],"attrs":{}},{"type":"text","text":" 類引用到上面的全局配置的處理方法中,如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"import Vue from \"vue\";\nimport { logger } from \"@/logger\";\n/**\n *\n * @param {*} error 錯誤跟蹤\n * @param {*} vm 組件錯誤\n * @param {*} info 特定的錯誤信息,如生命週期鉤子、事件等。\n */\nVue.config.errorHandler = (error, vm, info) => {\n logger.toServer({ error, vm, info });\n};\n\nwindow.onerror = function (message, source, lineno, colno, error) {\n logger.toServer({ message, source, lineno, colno, error });\n};\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"錯誤處理對於應用程序非常重要,在本文中,討論了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Vue.config.errorHandler","attrs":{}}],"attrs":{}},{"type":"text","text":" 使用生命週期鉤子的全局錯誤處理程序和自定義組件來處理可預知的異常。本文提供了基本細節,藉助這些細節,可以輕鬆實現應用程序的錯誤處理並記錄它們,這將有助於創建更好的用戶體驗。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章