[TOC]

对于前端应用来说, 对异常的监控是很有必要的。异常也有很多种,比如 js 运行时异常,加载静态资源异常,接口请求异常等等。今天就来大概了解一下如何进行异常监控。

JavaScript 运行时异常

try…catch

一般我们写代码时,会使用 try…catch 来捕获异常:

try {
  throw "出错了!";
  } catch (e) {
  console.log(e); // "出错了!"
}

在 try 代码块中,我们可以通过 throw 手动抛出异常,异常我们可以自定义,catch 代码块的参数是就是我们抛出来的异常。
当我们代码运行时发生错误时,会自动抛出来一个异常,这个异常是一个 Error 对象,会带有 name 和 message 两个标准属性。

现在大部分浏览器都支持了 stack 属性,包含错误的完整信息,包括了 name 、 message 和发生错误的文件和行号等。

try {
  console.log(a);
  const a = 123;
} catch (e) {
  console.log(e.name); // 'ReferenceError'
  console.log(e.message); // 'Cannot access 'a' before initialization'
  console.log(e.stack); // ReferenceError: Cannot access 'a' before initialization   at test.html:23
}

但是我们并不能使用 try…catch 来做整个 Web 应用的异常监控,因为我们不可能给所有的 js 代码都加上 try…catch。

window.onerror

当 JavaScript 运行时错误(包括语法错误)发生时,window 会触发一个 ErrorEvent 接口的 error 事件,并执行 window.onerror()
因此我们可以使用 window.onerror 来监控运行时的代码异常:

/**
 * message: 错误信息
 * source: 出错文件:
 * lineno: 出错行号
 * colno: 出错列号:
 * error: 错误详情
 */
window.onerror = function (message, source, lineno, colno, error) {
  // Todo: 异常上报
  return true; // 函数返回true,阻止执行默认事件处理函数,即浏览器控制台不会再打印错误信息
};

需要注意的是,当加载自不同域的脚本中发生语法错误时,为避免信息泄露,语法错误的细节将不会报告,而代之简单的”Script error.”。onerror 捕获的错误信息为:

message: "Script error."
source: ""
lineno: 0
colno: 0
error: null


如果需要解决这个问题的话,我们需要做两件事:

  • 引用跨域 js 文件时加上 crossorigin 属性

    <script type="text/javascript" src="http://b.com/b.js" crossorigin></script>
    
  • 服务器发送相关跨域 js 文件时需要发送适当的 CORS HTTP 响应头(Access-Control-Allow-Origin)

静态资源异常

当一项资源(如 前端异常监控 - 图1