前端代碼錯誤上報

對於前端來講,每每是用戶反饋了才知道已經錯了。javascript

爲了讓前端也能和後端同樣,須要將線上的 JavaScript 代碼監控起來,當用戶端瀏覽器出現異前端第一時間被通知到。前端

採集哪些數據

主要原則就是避開用戶敏感字段,採集瀏覽器版本、操做系統版本、報錯的 msg 信息等。java

如何採集錯誤

前端錯誤大致上能夠分紅兩類,webpack

  1. 代碼執行的錯誤web

  2. 資源加載的錯誤ajax

代碼執行錯誤

try……catch

try {
  init();
  // code...
} catch(e){
  Reporter.send(format(e));
}
複製代碼

try-catch是最弱雞的, 缺點是小程序

  1. 使用try... catch 包裹,影響代碼可讀性。後端

  2. 沒法處理語法錯誤微信小程序

    try {
      var error = 'error'// 中文輸入法的;
    } catch(e) {
      console.log('我感知不到錯誤');
      console.log(e);
    }
    複製代碼
  3. 沒法處理異步中的錯誤promise

    try {
      setTimeout(() => {
        error        // 異步錯誤
      })
    } catch(e) {
      console.log('我感知不到錯誤');
      console.log(e);
    }
    複製代碼

window.onerror

window.onerror要強那麼一丟丟。不管是異步仍是非異步錯誤,onerror 都能捕獲到運行時錯誤。

/** * @param {String} errorMessage 錯誤信息 * @param {String} scriptURI 出錯的文件 * @param {Long} lineNumber 出錯代碼的行號 * @param {Long} columnNumber 出錯代碼的列號 * @param {Object} errorObj 錯誤的詳細信息,Anything */
window.onerror = function(errorMessage, scriptURI, lineNumber, columnNumber, errorObj) { 
    // code..
}
複製代碼

window.onerror 的缺點:

  1. 監聽不到資源加載的報錯

  2. onerror 事件處理函數只能聲明一次,不會重複執行多個回調:

window.addEventListener('error')

window.addEventListener 能夠監聽到資源加載報錯,也能夠註冊多個事件處理函數。

var fn = window.onerror = function() {   // 只能監聽到js執行的錯誤,沒法監聽資源加載的錯誤
  console.log(arguments);
};
window.addEventListener("error", fn);    // 能夠監聽到js執行的錯誤,和資源加載的錯誤
window.addEventListener("error", fn);​
複製代碼

爲捕獲狀態時(第三個參數爲true)能捕獲到js執行錯誤,也能捕獲帶有src的標籤元素的加載錯誤。

爲冒泡狀態時(第三個參數爲false)能捕獲到js執行錯誤,不能捕獲帶有src的標籤元素的加載錯誤。

window.onerror vs window.addEventListener('error')

  1. onerror 只能聲明一次,而事件處理器則能夠綁定多個回調函數。

  2. onerror 沒有辦法監聽到資源加載的報錯,而 addEventListener 則能夠監聽到。

promise 中的異常

promise 的報錯比較嬌貴,try ……catch, window.onerror, widow.addEventlistener 都沒法監聽到promise 的報錯。

promise 中的報錯順序是:

  1. 若是有catch 等捕獲函數,則走catch 捕獲函數。catch 捕獲函數若是沒有拋出新的異常,則下一個then將會認爲沒有什麼報錯,every thing is so good , 會繼續執行。

  2. 若是沒有catch 等捕獲函數,咱們須要註冊 window.addEventListener('unhandledrejection') 來處理。

微信小程序 app.onError

App({
onError(msg) {
 this.monitor.onError(msg);
 },
})
複製代碼

微信小程序代碼中沒有辦法獲取到window對象,天然不能用window.onError, 小程序官方提供了 app.onError的方法。

sourceMap

生產環境的代碼是 webpack 混淆打包以後,很差定位。

解決辦法是開啓webpacksource-map,咱們利用webpack打包後的生成的一份.map的腳本文件就可讓瀏覽器對錯誤位置進行追蹤了。

var path = require('path');
module.exports = {
    devtool: 'source-map',
    mode: 'development',
    entry: './client/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'client')
    }
}
複製代碼

資源加載失敗

捕獲資源加載失敗的方法,主要以下:

  1. imgObj.onerror()

  2. performance.getEntries() 獲取到成功加載的資源,對比能夠間接的捕獲錯誤

  3. window.addEventListener('error', fn, true) 會捕獲可是不冒泡,因此window.onerror 不會觸發,捕獲階段能夠觸發

如何上報錯誤

  1. 採用ajax 上報

  2. 使用image上報

通常來講,大廠都是採用利用image對象的方式上報錯誤的;使用圖片發送get請求,上報信息,因爲瀏覽器對圖片有緩存,一樣的請求,圖片只會發送一次,避免重複上報。

var entry = {};
function report(url, data) {
    if (!url || !data) {
        return;
    }
    // @see http://jsperf.com/new-image-vs-createelement-img
    var image = document.createElement('img');
    var items = [];
    for (var key in data) {
        if (data[key]) {
            items.push(key + '=' + encodeURIComponent(data[key]));
        }
    }
    var name = 'img_' + (+new Date());
    entry[name] = image;
    image.onload = image.onerror = function () {
      console.log(arguments);
        entry[name] =
            image =
            image.onload =
            image.onerror = null;
        delete entry[name];
    };
    image.src = url + (url.indexOf('?') < 0 ? '?' : '&') + items.join('&');
}
複製代碼
相關文章
相關標籤/搜索