JS毛病監控總結

媒介

做好毛病監控,將用戶運用時的毛病日記上報,能夠協助我們更快的處置懲罰一些題目。現在開源的比較好的前端監控有

那前端監控是怎樣完成的呢?要想相識這個,須要曉得前端毛病也許分為哪些以及怎樣捕捉處置懲罰。

前端毛病分為JS運行時毛病、資本加載毛病和接口毛病三種。

一、JS運行時毛病

JS運行時毛病平常運用window.onerror捕捉,然則有一種迥殊狀況就是promise被reject而且毛病信息沒有被處置懲罰的時刻拋出的毛病

1.1 平常狀況的JS運行時毛病

運用window.onerror和window.addEventListener(‘error’)捕捉。个中window.onerror含有細緻的error信息(error.stack),而且兼容性更好,所以平常JS運行時毛病運用window.onerror捕捉處置懲罰

window.onerror = function (msg, url, lineNo, columnNo, error) 
    { 
       // 處置懲罰error信息
    } 
 
    window.addEventListener('error', event =>  
    {  
       console.log('addEventListener error:' + event.target); 
    }, true); 
    // true代表在捕捉階段挪用,false代表在冒泡階段捕捉。運用true或false都能夠

例子:
https://jsbin.com/lujahin/edit?html,console,output 點擊button拋出毛病,離別被window.onerror和window.addEventListener(‘error’)捕捉

1.2 Uncaught (in promise)

當promise被reject而且毛病信息沒有被處置懲罰的時刻,會拋出一個unhandledrejection,而且這個毛病不會被window.onerror以及window.addEventListener(‘error’)捕捉,須要用特地的window.addEventListener(‘unhandledrejection’)捕捉處置懲罰

window.addEventListener('unhandledrejection', event => 
    { 
       console.log('unhandledrejection:' + event.reason); // 捕捉后自定義處置懲罰
    });

https://developer.mozilla.org…

例子:
https://jsbin.com/jofomob/edit?html,console,output 點擊button拋出unhandledrejection毛病,而且該毛病僅能被window.addEventListener(‘unhandledrejection’)捕捉

1.3 console.error

一些迥殊狀況下,還須要捕捉處置懲罰console.error,捕捉體式格局就是重寫window.console.error

var consoleError = window.console.error; 
window.console.error = function () { 
    alert(JSON.stringify(arguments)); // 自定義處置懲罰
    consoleError && consoleError.apply(window, arguments); 
};

例子:
https://jsbin.com/pemigew/edit?html,console,output

1.4 迥殊申明跨域日記

什麼是跨域劇本error?

https://developer.mozilla.org…

當加載自差別域的劇本中發作語法毛病時,為防止信息泄漏(拜見bug 363897),語法毛病的細節將不會報告,而代之簡樸的”Script error.”。在某些瀏覽器中,經由過程在<script>運用crossorigin屬性並要求服務器發送恰當的 CORS HTTP 相應頭,該行動可被掩蓋。一個變通計劃是零丁處置懲罰”Script error.”,示知毛病概況僅能經由過程瀏覽器控制台檢察,沒法經由過程JavaScript接見。

例子: http://sandbox.runjs.cn/show/… 請翻開頁面翻開控制台。該頁面離別加載了兩個差別域的js劇本,設置了crossorigin的window.onerror能夠報出細緻的毛病,沒有設置crossorigin只能報出’script error’,而且沒有毛病信息

1.5 迥殊申明sourceMap

在線上由於JS平常都是被緊縮或許打包(webpack)過,打包后的文件只要一行,因而報錯會湧現第一行第5000列湧現JS毛病,給排查帶來難題。sourceMap存儲打包前的JS文件和打包后的JS文件之間一個映照關聯,能夠依據打包后的位置疾速解析出對應源文件的位置。

然則出於安全性斟酌,線上設置sourceMap會存在不安全的題目,由於網站運用者能夠隨意馬虎的看到網站源碼,此時能夠設置.map文件只能經由過程公司內網接見下降隱患

sourceMap設置devtool: ‘inline-source-map’

假如運用了uglifyjs-webpack-plugin 必需把 sourceMap設置為true

https://doc.webpack-china.org…

1.6 別的

1.6.1 sentry把一切的回調函數運用try catch封裝一層
https://github.com/getsentry/raven-js/blob/master/src/raven.js

1.6.2 vue errorHandler
https://vuejs.org/v2/api/#errorHandler
其道理也是運用try catch封裝了nextTick,$emit, watch,data等
https://github.com/vuejs/vue/blob/dev/dist/vue.runtime.js

二、資本加載毛病

運用window.addEventListener(‘error’)捕捉,window.onerror捕捉不到資本加載毛病

https://jsbin.com/rigasek/edit?html,console 圖片資本加載毛病。此時只要window.addEventListener(‘error’)能夠捕捉到

window.onerror和window.addEventListener(‘error’)的異同:相同點是都能夠捕捉到window上的js運行時毛病。區別是1.捕捉到的毛病參數差別 2.window.addEventListener(‘error’)能夠捕捉資本加載毛病,然則window.onerror不能捕捉到資本加載毛病

三、接口毛病

一切http要求都是基於xmlHttpRequest或許fetch封裝的。所以要捕捉全局的接口毛病,要領就是封裝xmlHttpRequest或許fetch

3.1 封裝xmlHttpRequest

if(!window.XMLHttpRequest) return;
var xmlhttp = window.XMLHttpRequest;
var _oldSend = xmlhttp.prototype.send;
var _handleEvent = function (event) {
    if (event && event.currentTarget && event.currentTarget.status !== 200) {
          // 自定義毛病上報 }
}
xmlhttp.prototype.send = function () {
    if (this['addEventListener']) {
        this['addEventListener']('error', _handleEvent);
        this['addEventListener']('load', _handleEvent);
        this['addEventListener']('abort', _handleEvent);
    } else {
        var _oldStateChange = this['onreadystatechange'];
        this['onreadystatechange'] = function (event) {
            if (this.readyState === 4) {
                _handleEvent(event);
            }
            _oldStateChange && _oldStateChange.apply(this, arguments);
        };
    }
    return _oldSend.apply(this, arguments);
}

3.2 封裝fetch

if(!window.fetch) return;
    let _oldFetch = window.fetch;
    window.fetch = function () {
        return _oldFetch.apply(this, arguments)
        .then(res => {
            if (!res.ok) { // True if status is HTTP 2xx
                // 上報毛病
            }
            return res;
        })
        .catch(error => {
            // 上報毛病
            throw error;  
        })
}

結論

  1. 運用window.onerror捕捉JS運行時毛病
  2. 運用window.addEventListener(‘unhandledrejection’)捕捉未處置懲罰的promise reject毛病
  3. 重寫console.error捕捉console.error毛病
  4. 在跨域劇本上設置crossorigin=”anonymous”捕捉跨域劇本毛病
  5. window.addEventListener(‘error’)捕捉資本加載毛病。由於它也能捕捉js運行時毛病,為防止反覆上報js運行時毛病,此時只要event.srcElement inatanceof HTMLScriptElement或HTMLLinkElement或HTMLImageElement時才上報
  6. 重寫window.XMLHttpRequest和window.fetch捕捉要求毛病

應用以上道理,簡樸寫了一個JS監控,只處置懲罰了一些JS毛病,臨時沒有做和機能相干的監控
https://github.com/Lie8466/better-js

假如發明文章有毛病,迎接斧正。

    原文作者:深藍一人
    原文地址: https://segmentfault.com/a/1190000014672384
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞