前端錯誤監控


為什么要做前端錯誤監控?

1. 為了保證產品的質量

2. 有些問題只存在於線上特定的環境

3. 后端錯誤有監控,前端錯誤沒有監控

前端錯誤的分類

前端錯誤分為兩類: 即時運行錯誤資源加載錯誤

即使運行錯誤的捕獲方式

即時運行錯誤的捕獲方式分為兩類

  1. try...catch
  2. window.onerror

try...catch

通過try...catch我們能夠知道出錯的信息,並且也有堆棧信息可以知道在哪個文件第幾行第幾列發生錯誤

try {
           // 代碼段
        } catch (err) {
            console.log(err.message)
        }

缺點:

  1. 沒法捕捉try,catch塊,當前代碼塊有語法錯誤,JS解釋器壓根都不會執行當前這個代碼塊,所以也就沒辦法被catch住;
  2. 沒法捕捉到全局的錯誤事件,也即是只有try,catch的塊里邊運行出錯才會被你捕捉到,這里的塊你要理解成一個函數塊

關於第一個缺點,我們沒有任何解決辦法,但是一般語法階段我們是能在開發階段/或者用工具檢測到的,於是乎它就被忽略了

第二個缺點應該怎么理解呢? try...catch只能捕捉到當前執行流里邊的運行錯誤,對於異步回調來說,是不屬於這個try...catch塊的

window.onerror

全局捕獲。window.onerror一樣可以拿到出錯的信息以及文件名、行號、列號等信息,還可以在window.onerror最后return true讓瀏覽器不輸出錯誤信息到控制台

/*
         * @param msg{String}:錯誤消息
         * @param url{String}:引發錯誤的腳本的URL
         * @param line{Number}:發生錯誤的代碼行
         * @param colunm{Number}:發生錯誤的代碼列
         * @param error{object}:錯誤對象
         */

        window.onerror = function (msg, url, line, colunm, error) {
            // 返回 true 則錯誤消息不顯示在控制台,返回 false,則錯誤消息將會展示在控制台
            return true;
        }

最后window.onerror的實現方法

window.onerror = function (msg, url, line, col, error) {
            //沒有URL不上報!上報也不知道錯誤
            if (msg != "Script error." && !url) {
                return true;
            }
            
            setTimeout(function () {
                var data = {};
                //不一定所有瀏覽器都支持col參數
                col = col || (window.event && window.event.errorCharacter) || 0;

                data.url = url;
                data.line = line;
                data.col = col;
                if (!!error && !!error.stack) {
                    //如果瀏覽器有堆棧信息
                    //直接使用
                    data.msg = error.stack.toString();
                } else if (!!arguments.callee) {
                    //嘗試通過callee拿堆棧信息
                    var ext = [];
                    var f = arguments.callee.caller,
                        c = 3;
                    //這里只拿三層堆棧信息
                    while (f && (--c > 0)) {
                        ext.push(f.toString());
                        if (f === f.caller) {
                            break; //如果有環
                        }
                        f = f.caller;
                    }
                    ext = ext.join(",");
                    data.msg = ext;
                }
                //把data上報到后台!
                console.log(data)
            }, 0);
            
            return true;
        };

資源加載錯誤

object.onerror

img、script標簽都可以添加onerror事件,當資源請求失敗的時候,都會觸發該事件

 var img = document.getElementById('img');
        img.onerror=function(){
            console.log("出錯啦");
        }

 

performance.getEntries()

performance是h5的新特性之一,使用該方法能獲取到當前頁面已經加載到的資源,返回的是一個數組對象。下面給出一個例子

獲取頁面中沒有成功加載的圖片資源?

步驟一:通過performance.getEntries()獲取已經加載了的圖片資源

let arr = [],
            reg = (/\.jpg$|\.jpeg$|.png$|\.gif$/i);
        performance.getEntries().forEach(item => {
            if (reg.test(item.name)) {
               arr.push(item.name)
            }
        })

步驟二:獲取頁面中所有的img標簽

let imgList=document.getElementByTagname('img')

步驟三:利用獲取到的img的長度減去已經加載到的長度,如果大於0的部分,就是加載失敗的

let arr = [],
        imgList=null,
        num=0,
            reg = (/\.jpg$|\.jpeg$|.png$|\.gif$/i);
        performance.getEntries().forEach(item => {
            if (reg.test(item.name)) {
               arr.push(item.name)
            }
        })
        imgList=document.getElementsByTagName('img');
        num=imgList.length-arr.length;

Error事件捕獲

資源加載錯誤,雖然會阻止冒泡,但是不會阻止捕獲。true:捕獲,false:冒泡

// window.addEventListener第三個參數是true的時候是捕獲的過程,false是冒泡的過程 
window.addEventListener('error',function(e){
        console.log("捕獲",e)
    },true)

 

跨域的JS文件異常捕獲

為了提升web性能,大部分web產品都有CDN部署,將資源部署到不同的域名上,但是我們都知道瀏覽器是有同源策略的,當加載不同域名的腳本發生錯誤時,語法錯誤的細節不會報告,僅返回"Script error",針對這種問題,可以在服務器上設置"Access-Control-Allow-Origin:*",在請求資源的script標簽上加上crossorigin屬性即可

 <script src="xxxx/js/store.js" crossorigin></script>

 


免責聲明!

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



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