javascript错误捕获

吐槽君 分类:javascript

GlobalEventHandlers.onerror

混合事件 GlobalEventHandlers 的 onerror 属性是用于处理 error (en-US) 的事件
Error事件的事件处理程序,在各种目标对象的不同类型错误被触发:

  • 当JavaScript运行时错误(包括语法错误)发生时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror()。
  • 当一项资源(如<img>或<script>)加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror()处理函数。这些error事件不会向上冒泡到window,不过(至少在Firefox中)能被单一的window.addEventListener (en-US)捕获。

加载一个全局的error事件处理函数可用于自动收集错误报告

window.onerror

window.onerror = function(message, source, lineno, colno, error) { 
    // TODO 事件异常信息的处理
    return true or false
}
 

window.onerror接受参数:

  • message:错误信息(字符串)。可用于HTML onerror=""处理程序中的event。
  • source:发生错误的脚本URL(字符串)
  • lineno:发生错误的行号(数字)
  • colno:发生错误的列号(数字)
  • error:Error对象(对象)

若该函数返回true,则阻止执行默认事件处理函数。

示例

  • 定义一个onerror捕获错误的事件
window.onerror = handleErr
function handleErr(message, source, lineno, colno, error) {
    console.log("There was an error:",message, source, lineno, colno, error);
    return true
}
 
  • 执行下面语句去触发onerror事件:

如果我们想在chrome控制台中直接模拟这个过程,会发现,直接使用throw new Error,无法触发这个onerror,这个可能是因为控制台的环境跟页面环境不一样。

setTimeout(function () { throw new Error }, 1000);
 
  • 执行结果
There was an error: Script error.  0 0 null
 

当handleErr的返回值是false时,结果如下:

There was an error: Script error.  0 0 null
VM185:1 Uncaught Error //这里时是浏览器默认onerror处理事件
    at <anonymous>:1:32
 

window.addEventListener

ErrorEvent 类型的event包含有关事件和错误的所有信息。

window.addEventListener('error', function(event) { ... })
 

element.onerror

element.onerror使用单一Event参数的函数作为其处理函数。

element.onerror = function(event) { ... }
 

特别注意 Script error

加载自不同域的脚本中发生语法错误时,为避免信息泄露(参见bug 363897),语法错误的细节将不会报告,而代之简单的"Script error."

原因

跨域脚本

//当前域脚本文件
<!doctype html>
<html>
<head>
  <title>example.com/test</title>
</head>
<body>
  <script src="http://another-domain.com/app.js"></script>
  <script>
  window.onerror = function (message, url, line, column, error) {
    console.log(message, url, line, column, error);
  }
  foo(); // call function declared in app.js
  </script>
</body>
</html>

//another-domain.com域里的脚本文件app.js
function foo() {
  bar(); // ReferenceError: bar is not a function
}
 

当将此文档加载到浏览器中并执行JavaScript时,会将以下内容输出到控制台(通过window.onerror回调记录):

"Script error.", "", 0, 0, undefined
 

解决方案1:CORS+crossorigin

在某些浏览器中,通过在<script>使用crossorigin属性并要求服务器发送适当的 CORS HTTP 响应头,该行为可被覆盖

  1. 添加crossorigin =“ anonymous”脚本属性

这告诉浏览器应该“匿名”获取目标文件。这意味着在请求此文件时,浏览器不会将任何潜在的用户标识信息(例如cookie或HTTP凭据)传输到服务器。

<script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>
 

crossorigin:用于配置 CORS 的请求数据

crossorigin的值 描述
anonymous 对此元素的 CORS 请求将不设置凭据标志
use-credentials 对此元素的CORS请求将设置凭证标志;这意味着请求将提供凭据(cookies,http authentication 和客户端ssl证书)
"" 设置一个空的值,如 crossorigin 或 crossorigin="",和设置 anonymous 的效果一样。
  1. 添加跨源HTTP标识符CORS
Access-Control-Allow-Origin: *
 

通过设置Access-Control-Allow-Origin: *,服务器将向浏览器指示任何来源都可以获取此文件。或者,您可以将其限制为仅由您控制的已知来源

解决方案2:try / catch

有时,我们并不总是能够调整Web应用程序正在使用的脚本的HTTP标头。在这种情况下,有另一种方法:使用try / catch。

<script src="http://another-domain.com/app.js"></script>
<script>
window.onerror = function (message, url, line, column, error) {
  console.log(message, url, line, column, error);
}

try {
  foo(); // call function declared in app.js
} catch (e) {
  console.log(e);
  throw e; // intentionally re-throw (caught by window.onerror)
}
</script>

// another-domain.com/app.js
function foo() {
  bar(); // ReferenceError: bar is not a function
}
 

运行示例HTML会将以下两个条目输出到控制台:

=> ReferenceError: bar is not defined
     at foo (http://another-domain.com/b.js:2:3)
     at http://example.com/test/:15:3

=> "Script error.", "", 0, 0, undefined
 

来自try / catch的第一个控制台语句设法获得一个错误对象,该对象包含类型,消息和堆栈跟踪,包括文件名和行号。来自的第二个控制台语句window.onerror再次只能输出“脚本错误”。

解决方案3: 单独处理"Script error.",

通过代码告知用户错误详情仅能通过浏览器控制台查看,无法通过JavaScript访问。

window.onerror = function (msg, url, lineNo, columnNo, error) {
    var string = msg.toLowerCase();
    var substring = "script error";
    if (string.indexOf(substring) > -1){
        alert('Script Error: See Browser Console for Detail');
    } else {
        var message = [
            'Message: ' + msg,
            'URL: ' + url,
            'Line: ' + lineNo,
            'Column: ' + columnNo,
            'Error object: ' + JSON.stringify(error)
        ].join(' - ');

        alert(message);
    }
    return false;
};
 

参考文章

script-error

回复

我来回复
  • 暂无回复内容