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 响应头,该行为可被覆盖
- 添加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 的效果一样。 |
- 添加跨源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