js基礎 ---- 前端如何記錄瀏覽器報錯


一、瀏覽器常見的幾種報錯分類

  1、網絡連接

  2、http劫持

  3、服務器錯誤

  4、前端代碼錯誤

  5、前端兼容性問題

  6、用戶操作錯誤

  7、跨域問題

二、如何記錄這些問題

  一般在本地進行調試的時候 發生錯誤 我們一般習慣性的先看 console 查看日志是最簡單的 但是當項目上線后 這種辦法基本等於無效 

  1、如何收集錯誤信息

    (1)、虛擬機監控

      優點:是指標齊全,並且可以進行競品監控

      缺點:是反映不全,容易失真

      (2)、腳本監控

      優點:是可以收集海量真實數據

      缺點:是影響性能,采樣少的情況下容易失真

  2、常見的幾種記錄錯誤的方法

    (1)、訪問瀏覽器時間記錄 performance API

      在chrome瀏覽器控制台輸入Performance.timing,會得到記錄了一個瀏覽器訪問各階段的時間的對象。

      進行錯誤收集的時候,可以對比這些時間,看錯誤發生在什么階段

      DNS 查詢耗時 :domainLookupEnd - domainLookupStart

      TCP 鏈接耗時 :connectEnd - connectStart

      request 請求耗時 :responseEnd - responseStart

      解析 dom 樹耗時 : domComplete - domInteractive

      白屏時間 :responseStart - navigationStart

      domready 時間 :domContentLoadedEventEnd - navigationStart

      onload 時間 :loadEventEnd – navigationStart

    (2)、腳本錯誤收集 window.onerror

      window.onerror可以捕捉運行時錯誤,可以拿到出錯的信息,堆棧,出錯的文件、行號、列號  

      要注意以下幾點:

        要把window.onerror這個代碼塊分離出去,並且比其他腳本先執行(注意這個前提!)即可捕捉到語法錯誤。

        由於網絡請求異常事件不會冒泡,需要在捕獲階段進行處理

        不能捕獲promise的錯誤信息

        跨域資源需要專門處理,需要在script標簽加上crossorigin屬性,服務器設置Access-Control-Allow-Origin

        window.onerror 函數只有在返回 true 的時候,異常才不會向上拋出,否則即使是知道異常的發生控制台還是會顯示 Uncaught Error: xxxxx。

      解決方案:

          使用window.onerror和window.addEventListener('error')都能捕獲,但是window.onerror含有詳細的error堆棧信息,存在error.stack中,所以可以選擇使用         onerror的方式對js運行時錯誤進行捕獲。

          window.onerror = function (msg, url, lineNo, columnNo, error) {
            // 處理錯誤信息
          }
          // demo
          msg: Uncaught TypeError: Uncaught ReferenceError: a is not defined
          error.statck: TypeError: ReferenceError: a is not defined at http://xxxx.js:1:13
          window.addEventListener('error', event => (){
            // 處理錯誤信息
          }, false);
          // true代表在捕獲階段調用,false代表在冒泡階段捕獲。使用true或false都可以,默認為false

 

    (3)、promise的錯誤處理

        promise除了使用catch方法來捕獲錯誤,還可以使用window的unhandledrejection事件捕獲異常的

        window.addEventListener("unhandledrejection", function(e){
            // Event新增屬性
            // @prop {Promise} promise - 狀態為rejected的Promise實例
            // @prop {String|Object} reason - 異常信息或rejected的內容

            // 會阻止異常繼續拋出,不讓Uncaught(in promise) Error產生
            e.preventDefault()
        })
    (4)、try catch
        
無法捕捉到語法錯誤,只能捕捉運行時錯誤;
        可以拿到出錯的信息,堆棧,出錯的文件、行號、列號; 需要借助工具把所有的function塊以及文件塊加入try,catch,可以在這個階段打入更多的靜態信息。

           要注意的是try catch只能捕獲同步代碼的異常,對回調,setTimeout,promise等無能為力
          上報錯誤的方式

          后端提供接口,前端ajax上傳  

          創建一個新的圖片,url參數帶上錯誤信息

            function report(error) {
               var reportUrl = 'http://xxxx/report';
               new Image().src = reportUrl + 'error=' + error;
            }
    (5)、fetch與xhr錯誤的捕獲
        對於fetch和xhr,我們需要通過改寫它們的原生方法,在觸發錯誤時進行自動化的捕獲和上報。
        改寫fetch方法:
          function _errorFetchInit () {
            if(!window.fetch) return;
            
let _oldFetch = window.fetch;
            window.fetch = function () {
              return _oldFetch.apply(this, arguments)
              
.then(res => {
                      if (!res.ok) { // 當status不為2XX的時候,上報錯誤
                        }
                        return res;
                      }).catch(error => {
                          throw error;
                      })
                    }
                  }
          對於XMLHttpRequest的重寫:

              // xhr的處理
              function _errorAjaxInit () {
              let protocol = window.location.protocol;
              if (protocol === 'file:') return;
                // 處理XMLHttpRequest
                if (!window.XMLHttpRequest) {
                  return;
                }
                let xmlhttp = window.XMLHttpRequest;
                // 保存原生send方法
                let _oldSend = xmlhttp.prototype.send;
                let _handleEvent = function (event) {
                  try {
                    if (event && event.currentTarget && event.currentTarget.status !== 200) {
                    // event.currentTarget 即為構建的xhr實例
                    // event.currentTarget.response
                    // event.currentTarget.responseURL || event.currentTarget.ajaxUrl
                    // event.currentTarget.status
                    // event.currentTarget.statusText
                   });
                  }
                  } catch (e) {va
                console.log('Tool\'s error: ' + e);
                 }
                }
                xmlhttp.prototype.send = function () {
                  this.addEventListener('error', _handleEvent); // 失敗
                  this.addEventListener('load', _handleEvent); // 完成
                  this.addEventListener('abort', _handleEvent); // 取消
                  return _oldSend.apply(this, arguments);
                }
              }

         (6)、跨域錯誤

            當網站請求並執行一個托管在第三方域名下的腳本時,就可能遇到該錯誤。最常見的情形是使用 CDN 托管 JS 資源

            出於安全考慮,瀏覽器會刻意隱藏其他域的 JS 文件拋出的具體錯誤信息,這樣做可以有效避免敏感信息無意中被不受控制的第三方腳本捕獲。

            因此,瀏覽器只允許同域下的腳本捕獲具體錯誤信息,而其他腳本只知道發生了一個錯誤,但無法獲知錯誤的具體內容。

            解決:

              <script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>

              此步驟的作用是告知瀏覽器以匿名方式獲取目標腳本。這意味着請求腳本時不會向服務端發送潛在的用戶身份信息(例如 Cookies、HTTP 證書等)。

              添加跨域 HTTP 響應頭:

                Access-Control-Allow-Origin: * ||  Access-Control-Allow-Origin: http://test.com

三、Vue的錯誤捕捉
    vue內部發生的錯誤會被Vue攔截,因此vue提供方法給我們處理vue組件內部發生的錯誤。
      Vue.config.errorHandler = function (err, vm, info) {}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM