屏蔽脚本错误有什么用
本文是与Sentry.io合作创建的。 感谢您支持使SitePoint成为可能的合作伙伴。
如果您之前onerror
JavaScript onerror
事件进行过任何处理,则可能遇到以下情况:
Script error.
当错误源自其他来源(不同的域,端口或协议)提供JavaScript文件时,“脚本错误”是浏览器发送到onerror回调的内容 。 这很痛苦,因为即使发生错误,您也不知道错误是什么 ,也不知道错误是从哪个代码产生的。 这就是window.onerror
的全部目的-深入了解应用程序中未捕获的错误。
原因:跨域脚本
为了更好地了解正在发生的事情,请考虑以下示例HTML文档,假设该文档来自http://example.com/test:
<!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>
这是http://another-domain.com/app.js的内容。 它声明一个函数foo,其调用将始终引发ReferenceError。
// another-domain.com/app.js
function foo() {
bar(); // ReferenceError: bar is not a function
}
当将此文档加载到浏览器中并执行JavaScript时,会将以下内容输出到控制台(通过window.onerror
回调记录):
"Script error.", "", 0, 0, undefined
这不是JavaScript错误 ,出于安全原因,浏览器有意隐藏源自不同来源的脚本文件的错误。 这是为了避免脚本无意间将潜在的敏感信息泄漏到了它无法控制的onerror
回调中。 因此,浏览器仅使window.onerror
洞悉源自同一域的错误。 我们所知道的是发生了错误-没有别的!
我真的不是坏人!
尽管有良好的浏览器意图,但您还是有一些非常好的理由要了解由不同来源提供的脚本引发的错误:
- 您的应用程序JavaScript文件是通过其他主机名(例如static.sentry.io/app.js)提供的。
- 您正在使用从社区CDN提供的库,例如cdnjs或Google的托管库。
- 您正在使用仅从外部服务器提供服务的商业第三方JavaScript库。
但是不用担心! 仅需进行一些简单的调整,即可洞悉这些文件提供的JavaScript错误 。
修复:CORS属性和标题
为了了解来自不同来源的脚本引发JavaScript异常,您必须做两件事。
1.添加一个crossorigin="anonymous"
脚本属性
<script src="http://another-domain.com/app.js" crossorigin="anonymous"></script>
这告诉浏览器应该“匿名”获取目标文件。 这意味着在请求此文件时,浏览器不会将任何潜在的用户标识信息(例如cookie或HTTP凭据)传输到服务器。
2.添加跨源HTTP标头**
Access-Control-Allow-Origin: \*
CORS是跨源资源共享的缩写,它是一组API(主要是HTTP标头),用于规定应如何跨源下载和提供文件。
通过设置Access-Control-Allow-Origin: \*
,服务器向浏览器指示任何来源都可以获取此文件。 或者,您可以将其限制为仅由您控制的已知来源:
$ curl --head https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.js | \
grep -i "access-control-allow-origin"
Access-Control-Allow-Origin: *
完成上述两个步骤后,此脚本触发的任何错误都将报告给window.onerror
,就像任何常规的同域脚本一样。 因此,从一开始的onerror
示例就代替了“脚本错误”:
"ReferenceError: bar is not defined", "http://another-domain.com/app.js", 2, 1, [Object Error]
繁荣! 完成了-“脚本错误”将不再困扰您和您的团队。
替代解决方案: try/catch
有时,我们无法调整Web应用程序正在使用的脚本的HTTP标头。 在这种情况下,有另一种方法:使用try/catch
。
再次考虑原始示例,这次使用try/catch
:
<!-- note: crossorigin="anonymous" intentionally absent -->
<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>
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
为了后代,some-domain.com/app.js再次看起来像这样:
// 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
的第二个控制台语句只能输出“脚本错误”。
现在,这是否意味着您需要try/catch
所有代码? 可能不是。 如果您可以轻松更改HTML并在CDN上指定CORS标头,则最好这样做并坚持window.onerror
。
但是,如果您不控制这些资源,则使用try/catch
包装第三方代码是一种确保深入了解跨域脚本抛出的错误的可靠方法(尽管很乏味)。
注意:默认情况下, SentryJavaScript SDK raven.js会谨慎地使用内置方法来尝试自动将代码包装在try/catch
块中。 它这样做是为了尝试捕获所有脚本中的错误消息和堆栈跟踪信息,而不管它们来自何处。 如果可能,仍建议设置CORS属性和标头。
当然,有很多商业和开源工具可以为您完成所有繁重的客户端报告。 (Psst:您可能想尝试Sentry调试JavaScript。)
而已! 快乐的错误监控 。
翻译自: https://www.sitepoint.com/what-the-heck-does-script-error-mean/
屏蔽脚本错误有什么用