前端錯誤監控以及上報方法總結

捕獲錯誤的常見的幾種方法

Global​Event​Handlers​.onerror

windows下面的全局error事件程序,當有javaSript腳本運行錯誤或者資源<img>、<script>加載失敗時,都會觸發Event接口的error事件,也能被window.addEventListener捕獲到javascript

兩種寫法html

window.onerror = function(message, source, lineno, colno, error) { 
	console.log(message)//字符串錯誤信息
	console.log(source)//發生錯誤的腳本
	console.log(lineno)//發生錯誤的行號
	console.log(colno)//發生錯誤的列號
	console.log(error)//Erroe對象
	
	return true//將代碼錯誤定格在捕獲階段
}

window.addEventListener('error', (msg, url, row, col, error) => {
    console.log(
        msg, url, row, col, error
    );
    return true;
}, true);

複製代碼

注意前端

  • window.onerror只有在返回true時,異常纔不會向上拋出,原理是冒泡機制。並且window.onerror是沒法捕獲到網絡異常的,由於網絡請求異常不會事件冒泡,雖然能在捕獲階段捕獲到,可是沒法判斷HTTP的狀態碼,須要配合服務端才能排查。
  • 咱們平時寫window.onerror的時候,最好寫在最頂端,以避免前面的錯誤腳本阻斷了。同時在vue或者react框架中,他們有自身的錯誤捕獲機制,因此會掩蓋window.onerror,好比vue的Vue.config.errorHandler。想詳細瞭解看官網文檔便可。
try...catch...finally

這種方式應該是咱們平時用的最多的,具體功能想必你們也應該都很清楚,將咱們須要檢測的代碼包裹在try和catch中,當發生語法錯誤或者其餘錯誤時,就會從catch裏捕獲到,而無論前端發生了什麼,最後finally裏的代碼總會執行。vue

下面的代碼會怎麼執行,你們能夠思考一下java

try {
  try {
    throw new Error("oops");
  }
  catch (ex) {
    console.error("inner", ex.message);
    throw ex;
  }
  finally {
    console.log("finally");
    return;
  }
}
catch (ex) {
  console.error("outer", ex.message);
}
複製代碼

特別注意react

  • try...catch只能捕獲到運行時的非異步錯誤,而語法錯誤和異步錯誤就捕捉不到。
  • 還有一點就是try..catch比較消耗性能,能少用的最好。
unhandledrejection

有些錯誤try..catch和windows.onerror也是無能爲力的,好比說Promise實例從pending轉變爲rejected時,若是加了catch就會被捕獲到,但要是沒有加,那麼繼續拋出就會Uncaught(in promise) Errorwebpack

好比下面代碼就捕獲不到錯誤git

window.onerror = function(message, source, lineno, colno, error) { 
	console.log(message)//字符串錯誤信息
	console.log(source)//發生錯誤的腳本
	console.log(lineno)//發生錯誤的行號
	console.log(colno)//發生錯誤的列號
	console.log(error)//Erroe對象
	
	return true//將代碼錯誤定格在捕獲階段
}

  // 調用Promise.reject類方法
    Promise.reject('promise error');
    // 在工廠方法中調用reject方法
    new Promise((resolve, reject) => {
        reject('promise error');
    });
    // 在工廠方法或then回調函數中拋異常
    new Promise((resolve) => {
        resolve();
    }).then(() => {
        throw 'promise error'
    });
複製代碼

咱們能夠經過下面的方法監聽到github

window.addEventListener('unhandledrejection', function (event) {
  // ...your code here to handle the unhandled rejection...

  // Prevent the default handling (such as outputting the
  // error to the console

  event.preventDefault();
});
複製代碼

可是這方法的兼容性有點失望 web

unhandledrejection.png

What the heck is "Script error"?

‘Script error’ 這個錯誤是比較常見的,通常經過windows.onerror捕獲到後基本確實就是哪一個script文件有問題,並且這個文件仍是跨域的,既然是跨域致使信息不全,因此首先要解決的就是跨域問題,關於跨域方面的前端解決方案能夠看我這篇文章《前端常見跨域方案彙總》;

對於script標籤,咱們還須要額外配置一個參數crossOrigin

<script src='www.example.com' crossorigin></script>
複製代碼

至於服務端,經常使用的就是

瞭解sourceMap

對於這個功能的講解,看阮大神的講解是最適合不過的了,固然瞭解其基本設計思路也是很重要的,SourceMap其實就是一個信息文件,存儲着源文件的信息及源文件與處理後文件的映射關係。咱們平時vue或者react項目開發中,經過webpack配置在測試環境中默認開啓生成SourceMap,出現錯誤可以及時重現原代碼,可是正式環境咱們通常是不會將SourceMap文件發佈上去的,可是正式環境的代碼通常都是壓縮過的,因此若是報錯了,通常是很難 定位到原代碼的位置,這時候優秀的錯誤上傳功能,以及平臺處理錯誤分析就顯得尤其重要了。下圖就是大概的設計思路。

sourcemap.png

Navigator.sendBeacon()存在的意義

平時咱們很常見網頁卡頓或者直接崩潰,通常是經過window 對象的 load 和 beforeunload 事件實現了網頁崩潰的監控;具體看這篇文章,Logging Information on Browser Crashes

實現代碼

window.addEventListener('load', function () {
      sessionStorage.setItem('good_exit', 'pending');
      setInterval(function () {
         sessionStorage.setItem('time_before_crash', new Date().toString());
      }, 1000);
   });

   window.addEventListener('beforeunload', function () {
      sessionStorage.setItem('good_exit', 'true');
   });

   if(sessionStorage.getItem('good_exit') &&
      sessionStorage.getItem('good_exit') !== 'true') {
      /*
         insert crash logging code here
     */
      alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash'));
   }
複製代碼

可是上面的編碼模式存在不友好的問題,當咱們嘗試在卸載頁面前經過上傳服務器數據,爲了延遲頁面卸載,須要經過同步XMLHttpRequest 發送數據或者建立一個幾秒的循環來延遲卸載。這樣的處理可想而知不是很友好,這時候sendBeacon()就橫空出世了,很簡單的實現向服務器發送數據,同時又不會影響下一個頁面的加載,具體以下面簡單的代碼實現。

window.addEventListener('unload', logData, false);

function logData() {
    navigator.sendBeacon("www.youAddress.com", analyticsData);
}
複製代碼
擴展閱讀

7 天打造前端性能監控系統

成熟解決方案 badjssentryraven-js FunDebug

若是大神您想繼續探討或者學習更多知識,歡迎加入QQ或者微信一塊兒探討:854280588

QQ.png
微信
相關文章
相關標籤/搜索