核心要點
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中文網其他相關文章!