前端代码错误上报

对于前端来讲,每每是用户反馈了才知道已经错了。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('&');
}
复制代码
相关文章
相关标签/搜索