核心要点
onerror
回调函数发送“脚本错误”消息。这是出于安全考虑,防止意外泄漏潜在敏感信息。crossorigin="anonymous"
脚本属性和添加跨域 HTTP 头。这允许任何来源获取文件,并且脚本触发的任何错误都将报告给 window.onerror
。try/catch
作为替代方法。通过将第三方代码包装在 try/catch
块中,可以深入了解跨域脚本抛出的错误。但是,如果可能,仍然建议设置 CORS 属性和头。本文与 Sentry.io 合作创作。感谢您支持使 SitePoint 成为可能的合作伙伴。
如果您之前使用过 JavaScript 的 onerror
事件,您可能遇到过以下情况:
脚本错误。
当错误源于来自不同来源(不同的域名、端口或协议)的 JavaScript 文件时,浏览器会将“脚本错误”发送到 onerror
回调函数。这很痛苦,因为即使发生了错误,您也不知道错误是什么,也不知道错误源于哪个代码。而 window.onerror
的全部目的是深入了解应用程序中未捕获的错误。
原因:跨域脚本
为了更好地理解正在发生的事情,请考虑以下示例 HTML 文档,假设它来自 http://example.com/test
:
<!DOCTYPE html> <html> <head> <title>example.com/test</title> </head> <body> <🎜> <🎜> </body> </html>
这是 http://another-domain.com/app.js
的内容。它声明了一个名为 foo
的单个函数,其调用将始终抛出 ReferenceError
。
// another-domain.com/app.js function foo() { bar(); // ReferenceError: bar 不是函数 }
当此文档在浏览器中加载并执行 JavaScript 时,以下内容将输出到控制台(通过 window.onerror
回调函数记录):
"脚本错误。", "", 0, 0, undefined
这不是 JavaScript 错误——浏览器故意出于安全原因隐藏来自不同来源的脚本文件的错误。这是为了避免脚本无意中将潜在的敏感信息泄漏到它无法控制的 onerror
回调函数中。因此,浏览器只允许 window.onerror
深入了解源于同一域的错误。我们只知道发生了错误——除此之外什么都不知道!
我不是坏人,真的!
尽管浏览器的意图良好,但您希望深入了解由不同来源的脚本抛出的错误,有一些非常好的理由:
static.sentry.io/app.js
)。但别担心!深入了解由这些文件提供的 JavaScript 错误只需要一些简单的调整。
解决方案:CORS 属性和头
为了了解由不同来源的脚本抛出的 JavaScript 异常,您必须执行两件事。
crossorigin="anonymous"
脚本属性<!DOCTYPE html> <html> <head> <title>example.com/test</title> </head> <body> <🎜> <🎜> </body> </html>
这告诉浏览器目标文件应该“匿名”获取。这意味着当请求此文件时,浏览器不会向服务器传输任何潜在的用户识别信息,如 Cookie 或 HTTP 凭据。
// another-domain.com/app.js function foo() { bar(); // ReferenceError: bar 不是函数 }
CORS 是跨域资源共享的缩写,它是一组 API(主要是 HTTP 头),用于规定如何跨域下载和提供文件。
通过设置 <code>Access-Control-Allow-Origin: *</code>,服务器向浏览器指示任何来源都可以获取此文件。或者,您可以将其限制为您控制的已知来源:
<🎜>
一旦完成了这两个步骤,此脚本触发的任何错误都将报告给 window.onerror
,就像任何常规的同域脚本一样。因此,onerror
示例将不再是“脚本错误”,而是:
<code>Access-Control-Allow-Origin: *</code>
就是这样!“脚本错误”将不再困扰您和您的团队。
替代方案:try/catch
有时我们无法调整我们的 Web 应用程序正在使用的脚本的 HTTP 头。在这种情况下,有一种替代方法:使用 try/catch
。
再次考虑原始示例,这次使用 try/catch
:
$ curl --head https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.js | \ grep -i "access-control-allow-origin" Access-Control-Allow-Origin: *
为了后代考虑,some-domain.com/app.js
再次如下所示:
<code>"ReferenceError: bar 未定义", "http://another-domain.com/app.js", 2, 1, [Object Error]</code>
运行示例 HTML 将输出以下两个条目到控制台:
window.onerror = function (message, url, line, column, error) { console.log(message, url, line, column, error); } try { foo(); // 调用 app.js 中声明的函数 } catch (e) { console.log(e); throw e; // 故意重新抛出(由 window.onerror 捕获) }
第一个控制台语句——来自 try/catch
——设法获取了一个错误对象,其中包含类型、消息和堆栈跟踪,包括文件名和行号。来自 window.onerror
的第二个控制台语句再次只能输出“脚本错误”。
现在,这是否意味着您需要尝试捕获所有代码?可能不是。如果您能轻松更改 HTML 并指定 CDN 上的 CORS 头,最好这样做并坚持使用 window.onerror
。
但是,如果您不控制这些资源,使用 try/catch
包装第三方代码是获得对跨域脚本抛出的错误的深入了解的可靠(尽管很繁琐)的方法。
注意:默认情况下,Sentry 的 JavaScript SDK raven.js 会仔细地检测内置方法,以尝试自动将您的代码包装在 try/catch
块中。这样做是为了尝试捕获所有脚本的错误消息和堆栈跟踪,无论它们来自哪个来源。如果可能,仍然建议设置 CORS 属性和头。
当然,有很多商业和开源工具可以为您完成所有繁重的工作。(嘘:您可能想尝试使用 Sentry 调试 JavaScript。)
就是这样!祝您错误监控愉快。
脚本错误常见问题解答
(此处省略了FAQ部分,因为篇幅过长,且与文章主题关联性较弱,可以根据需要自行添加或修改FAQ)
以上是'脚本错误”是什么意思?的详细内容。更多信息请关注PHP中文网其他相关文章!