優雅處理前端異常的幾種方式推薦
一、為什麼要處理異常?
1、未雨綢繆,盡早發現問題
2、讓異常變得可控,避免影響呈現結果
3、增強用戶體驗
4、完善的前端方案
二、需要處理哪些異常?
1、JavaScript 語法錯誤、代碼異常
2、異步請求異常
3、靜態資源加載異常
4、Promise 異常
5、跨域
6、崩潰與渲染異常
三、處理異常的方式有哪些?
1、try-catch
我們可以使用 try-catch 對同步代碼運行異常進行捕獲。
例如:
try { let name = 'leo'; console.log(age); } catch(e) { console.log('捕獲到異常:',e); } // 捕獲到異常: ReferenceError: age is not defined
try-catch 無法捕獲語法錯誤和異步錯誤。
例如:
try { let name = 'leo; // 缺少一個單引號,屬於語法錯誤,在開發階段便提示出來 console.log(age); } catch(e) { console.log('捕獲到異常:',e); } // Uncaught SyntaxError: Invalid or unexpected token
try { setTimeout(() => { undefined.map(v => v*2); }, 1000) } catch(e) { console.log('捕獲到異常:',e); }
由於 setTimeout 屬於異步,try-catch 並沒有捕獲到,查看日志
// Uncaught TypeError: Cannot read property 'map' of undefined
2、window.onerror
我們可以使用 window.onerror 對 JavaScript 運行錯誤時進行捕獲。
window.onerror = function(message, source, lineNo, colNo, error) { console.log('捕獲到異常:',{message, source, lineNo, colNo, error}); } /** * message 錯誤信息 * source 出錯文件 * lineNo 行號 * colNo 列號 * error Error對象(對象) */
同步運行錯誤
window.onerror = function(message, source, lineNo, colNo, error) { console.log('捕獲到異常:',{message, source, lineNo, colNo, error}); } leo;
捕獲到異常
語法錯誤
window.onerror = function(message, source, lineNo, colNo, error) { console.log('捕獲到異常:',{message, source, lineNo, colNo, error}); } let name = 'leo
與 try-catch 一樣,無法捕獲語法錯誤。
異步運行錯誤
window.onerror = function(message, source, lineNo, colNo, error) { console.log('捕獲到異常:',{message, source, lineNo, colNo, error}); } setTimeout(() => { leo; },1000)
捕獲到異常
window.onerror 在捕獲到錯誤時,會向上拋出,如上例,控制臺會出現
我們可以在函數裡面使用 return true,使異常不向上拋出,此時控制臺不會顯示如上錯誤信息
window.onerror = function(message, source, lineNo, colNo, error) { console.log('捕獲到異常:',{message, source, lineNo, colNo, error}); return true; // 異常不向上拋出 } setTimeout(() => { leo; },1000)
window.onerror 最好寫在所有 JavaScript 腳本前面,否則有可能捕獲不到異常;
window.onerror 無法捕獲語法異常、靜態資源異常、接口請求異常;
window.onerror 主要用來捕獲意料之外的異常,而 try-catch 則是用來捕獲可預見的異常。
3、window.addEventListener
我們可以使用 window.addEventListener 對靜態資源加載異常與接口請求異常進行捕獲。
<scritp> window.addEventListener('error', (error) => { console.log('捕獲到異常:', error); }, true) </script> <img src="../../assets/test.png">
捕獲到異常
當一項資源(如圖片或腳本)加載失敗,加載資源的元素會觸發一個 Event 接口的 error 事件,並執行該元素上的 onerror 處理函數。
由於網絡請求異常不會事件冒泡,因此必須在捕獲階段將其捕捉到才行,但是這種方式雖然可以捕捉到網絡請求的異常,但是無法判斷狀態碼是 404 還是其他比如 500 等等,所以還需要配合服務端日志才進行排查分析才可以。
不同的瀏覽器返回的 error 對象可能不一樣,需要做兼容;
避免 addEventListener 重復監聽。
4、Promise catch
我們可以使用 Promise 中的 catch 捕獲異步錯誤。
new Promise((resolve,reject) => { reject("執行失敗!") }).catch(error => { console.log("捕獲到異常:",error) })
捕獲到異常
有時候我們在寫 Promise 可能會漏掉 catch,所以建議在全局增加一個對 unhandledrejection 的監聽,用來全局監聽 Uncaught Promise Error。
window.addEventListener("unhandledrejection", function(e){ e.preventDefault() console.log('捕獲到異常:', e); }); new Promise((resolve,reject) => { reject("執行失敗!") })
捕獲到異常
添加 event.preventDefault(); 可以去掉控制臺的異常顯示信息。
5、vue errorHandler
我們可以使用 errorHandler 對 vue 組件中所拋錯誤的捕捉與處理。
Vue.config.errorHandler = (err, vm, info) => { console.error(err); console.error(vm); console.error(info); } // 某個組件的 mounted const error = new Error('test error'); error.code = -1; throw error;
捕獲到異常
6、 react 異常捕獲
React 16 提供瞭一個內置函數 componentDidCatch
,使用它可以非常簡單的獲取到 react
下的錯誤信息。
componentDidCatch(error, info) { console.log(error, info); }
除此之外,也可以使用錯誤邊界 error boundary,此處不展開。
7、跨域
資源跨域可以為 script
標簽添加 crossOrigin
屬性。
<script src="http://localhost:3000/main.js" crossorigin></script>
也可以動態添加 JavaScript 腳本
const script = document.createElement('script'); script.crossOrigin = 'anonymous'; script.src = url; document.body.appendChild(script);
四、總結
處理異常方式 | 說明 |
---|---|
try-catch | 可預見、可疑區域 |
window.onerror | 全局捕獲 JavaScript 異常 |
window.addEventListener | 全局捕獲靜態資源異常 |
Promise catch | 捕獲 Promise 異常,也可使用 unhandledrejection 進行全局捕獲 |
vue errorHandler | 捕獲 vue 異常 |
react 異常捕獲 | 捕獲 react 異常 |
crossOrigin | 解決 JavaScript 腳本跨域 |
到此這篇關於優雅處理前端異常的幾種方式文章就介紹到這瞭,更多相關優雅處理前端異常內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
參考:如何優雅處理前端異常? – Jartto's blog
推薦閱讀:
- JavaScript基礎入門之錯誤捕獲機制
- JavsScript中Promise的錯誤捕獲詳解
- vue中Promise的使用方法詳情
- 詳解JavaScript錯誤捕獲
- 前端JavaScript之Promise