前端如何收集錯誤(原生,Vue)
如何捕獲異常
JS異常
js異常的特點是,出現不會導致JS引擎崩潰,最多隻會終止當前執行的任務。
比如一個頁面有兩個按鈕,如果點選按鈕導致頁面發生異常,這個時候頁面不會崩潰。
只是這個按鈕的功能失效,其他按鈕還會有效
上面的例子我們用setTimeout分別啟動了兩個任務。
雖然第一個任務執行了一個錯誤的方法。程式執行停止了。但是另外一個任務並沒有收到影響。
其實如果你不開啟控制檯都看不到發生了錯誤。好像是錯誤是在靜默中發生的。
下面我們來看看這樣的錯誤該如何收集。
try-catch:
如果在函式中錯誤沒有被捕獲,錯誤會上拋。
控制檯中打印出的分別是錯誤資訊和錯誤堆疊。
讀到這裡大家可能會想那就在最底層做一個錯誤try-catch不就好了嗎。
確實作為一個從java轉過來的程式設計師也是這麼想的。
但是理想很豐滿,現實很骨感。我們看看下一個例子。
大家注意執行結果,異常並沒有被捕獲。
這是因為JS的try-catch功能非常有限一遇到非同步就不好用了。
那總不能為了收集錯誤給所有的非同步都加一個try-catch吧,太坑爹了。
其實你想想非同步任務其實也不是由程式碼形式上的上層呼叫的就比如本例中的setTimeout。
大家想想eventloop就明白啦,其實這些非同步函式都是就好比一群沒孃的孩子出了錯誤找不到家大人。
當然我也想過一些黑魔法來處理這個問題比如代理執行或者用過的非同步方法。
算了還是還是再看看吧。
異常任務捕獲
window.onerror:
window.onerror 最大的好處就是同步任務、非同步任務都可捕獲。
onerror返回值
onerror還有一個問題大家要注意 如果返回true 就不會被上拋了。
不然控制檯中還會看到錯誤日誌。
監聽error事件:
檔案中的位置☟
window.addEventListener('error',() => {})
其實 onerror 固然好但是還是有一類異常無法捕獲。這就是網路異常的錯誤。
比如下面的例子。
<img src="./xxxxx.png">
試想一下我們如果頁面上要顯示的圖片突然不顯示了,而我們渾然不知那就是麻煩了。
addEventListener就解決這個問題:
執行結果如下:
Promise異常捕獲:
Promise 的出現主要是為了讓我們解決回撥地域問題。基本是我們程式開發的標配了。
雖然我們提倡使用 es7 async/await 語法來寫。
但是不排除很多祖傳程式碼還是存在Promise寫法。
new Promise((resolve, reject) => {
abcxxx()
});
這種情況無論是onerror還是監聽錯誤事件都是無法捕獲的。
除非每個Promise都新增一個catch方法。
但顯然,我們不能這樣做.
window.addEventListener("unhandledrejection", e => {
console.log('unhandledrejection',e)
});
我們可以考慮將unhandledrejection事件捕獲的錯誤丟擲交由錯誤事件統一處理就可以了。
async/await異常捕獲:
實際上async/await語法本質還是Promise語法。
區別就是async方法可以被上層的try/catch捕獲。
如果不去捕獲的話就會和Promise一樣,需要用unhandledrejection事件捕獲。
這樣的話我們只需要在全域性增加unhandlerejection就好了。
小結:
實際上我們可以將unhandledrejection事件丟擲的異常再次丟擲就可以統一通過error事件進行處理了。
最終用程式碼表示如下:
VUE工程
利用vue-cli工具直接建立一個專案。
為了測試的需要我們暫時關閉eslint 這裡面還是建議大家全程開啟eslint。
在vue.config.js進行配置
我們故意在(檔案位置☟)
src/components/HelloWorld.vue
這個時候 錯誤會在控制檯中被打印出來,但是錯誤事件並沒有監聽到。
errorHandle 控制代碼:
為了對Vue發生的異常進行統一的上報,需要利用vue提供的errorHandle控制代碼。
一旦Vue發生異常都會呼叫這個方法。
我們在src/main.js
文章轉載自:從 0 到 1 搭建前端異常監控系統
作者:熊貓吃西瓜 出處:https://www.cnblogs.com/XF-eng 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須在文章頁面給出原文連線,否則保留追究法律責任的權利。