今天讲下Vue项目的的脚本错误捕获。

一、JS 脚本

一般的前端项目错误捕获是在window.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) {
        
        let errorData = {
            message:errorMessage ,
            stackinfo: errorObj,   
        };   

        reportJsError({
            code: 'xxxxx',
            msg: errorData,
            action: 'js-global-error',
            file: encodeURIComponent(location.href),   
            line: lineNumber,        
        });    
    }

在onerror方法中会返回错误信息,错误文件等一系列的信息。需要注意的有下面2个点:

1、浏览器兼容性。

   此方法有一定的浏览器兼容性,具体情况如下:

2、跨域脚本情况。

    当加载自不同域的脚本中发生语法错误时,errorMessage始终是‘Script error.’,lineNumber 为0。通过在<script>使用crossorigin属行来规避这种个情况。

 

二、Vue 项目下的错误捕获。

在Vue 2.2.0以上的项目用window.onerror并不能捕获.vue文件发生的获取(其他的版本未进行测试)。为什么会出现这种情况呢?原因是在Vue 2.2.0以上的版本中增加了一个errorHandle,通过配置此方法可以捕获Vue文件在渲染和观察期间出现的错误。

Vue.config.errorHandler = function (err, vm, info) {
  // handle error
  // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
  // 只在 2.2.0+ 可用
}

很多同学就会疑惑,为什么会这样呢?我们来看下Vue的源码,发现里面有一个error.js文件,路径在`src/core/util`,源码比较少,就直接贴出来。

export function handleError (err: Error, vm: any, info: string) {
  if (vm) {
    let cur = vm
    while ((cur = cur.$parent)) {
      const hooks = cur.$options.errorCaptured
      if (hooks) {
        for (let i = 0; i < hooks.length; i++) {
          try {
            const capture = hooks[i].call(cur, err, vm, info) === false
            if (capture) return
          } catch (e) {
            globalHandleError(e, cur, 'errorCaptured hook')
          }
        }
      }
    }
  }
  globalHandleError(err, vm, info)
}

function globalHandleError (err, vm, info) {
  if (config.errorHandler) {
    try {
      return config.errorHandler.call(null, err, vm, info)
    } catch (e) {
      logError(e, null, 'config.errorHandler')
    }
  }
  logError(err, vm, info)
}

function logError (err, vm, info) {
  if (process.env.NODE_ENV !== 'production') {
    warn(`Error in ${info}: "${err.toString()}"`, vm)
  }
  /* istanbul ignore else */
  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
    console.error(err)
  } else {
    throw err
  }
}

其他地方不需要关系,直接看globalHandleError的定义,里面有一个逻辑判断验证是否定义了errorHandler,未定义errorHandler处理函数直接走logError方法。

在logError方法中的路径也很清晰,所以在开发模式下,或者在一般浏览器下weex下是不会再抛出错误了。这就是用window.onerror不能再捕获错误原因。

文章结束,如有纰漏欢迎指正~~。

参考资料:

GlobalEventHandlers.onerror

What the heck is "Script error"

errorHandler

Logo

前往低代码交流专区

更多推荐