[英]Logging client-side errors and “Script error”
如何查明來自其他域的腳本中發生的客戶端錯誤?
為清楚起見,我們假設我們有一個平均大小的Web應用程序,它使用由其他域托管的多個腳本(如google maps JS SDK)。
有一天,您開始在錯誤日志中收到Script error
,這意味着第三方代碼中發生了錯誤。
但是,如何在代碼中找到調用最終失敗的第三方代碼的確切方法?
PS:開發人員無法重現錯誤,而且很少發生在客戶端計算機上。
PPS:對於window.onerror
以上的錯誤, 不提供調用堆棧,正確的錯誤消息,文件名和行號。 所以它提供了幾乎沒有任何幫助的Script error
錯誤消息。
PPPS:
使用<script src="http://..."></script>
標記包含第三方腳本,並使用someFunctionFromTheThirdPartyScript();
執行someFunctionFromTheThirdPartyScript();
我有過類似的問題,我的解決方案是......
// The parameters are automatically passed to the window.onerror handler...
function myErrorFunction(message, url, linenumber) {
$.post(
"https://host.and/path/to/script/that/stores/entries",
{
"url":url, // URL of the page where the error occured
"lineNumber":linenumber, // Line number where the error occer
"message":message //error message
},
function(){
//callback function for the $.post()
if(console)
if(console.log)
console.log("Error reported.");
}
);
}
window.onerror = myErrorFunction; //adds function "myErrorFunction" to the onError Event
為了更復雜,你需要利用我在調試項目中使用的一些技巧: https : //github.com/luke80/JavaScript-DebugTools-Luke
編輯:好的,我將從該項目中收集適用於您的問題的重要部分:
/*
String prototype .hashCode()
From: http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery
*/
if(typeof String['hashCode'] == "undefined") {
String.prototype.hashCode = function(){
var hash = 0, i, char;
if (this.length == 0) return hash;
for (i = 0, l = this.length; i < l; i++) {
char = this.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
// Start of vars
var _LOG_CALLERARGS_ON = true,
getCallerHash = function(funcString) {
return callerFunc.toString().hashCode();
},
getCallerArgs = function(obj) {
return JSON.stringify(Array.prototype.slice.call(obj),this._detectCircularity(Array.prototype.slice.call(obj))).replace(/^\[/,"(").replace(/\]$/,")");
},
detectCircularity = function(obj) { // From: http://stackoverflow.com/questions/4816099/chrome-sendrequest-error-typeerror-converting-circular-structure-to-json
return (function() {
var i = 0;
return function(key, value) {
if(i !== 0 && typeof(obj) === 'object' && typeof(value) == 'object' && obj == value) return '[Circular]';
if(i >= 29) return '[Too deep, not mined]';
++i;
return value;
}
})(detectCircularity);
},
caller = this.o.caller || arguments.callee.caller || "top";
// End of vars
if(typeof caller != "string") {
if(caller) {
var callerData = ((caller.name)?caller.name:"Unnamed Caller:"+getCallerHash(caller))+((_LOG_CALLERARGS_ON)?getCallerArgs(caller.arguments):"");
// Since this loop could easily become problematic (infinite loop, anyone?) lets impose a limit.
var maxLoops = 64;
var loopCounter = 0;
// Now we gather all (or 64 of them) the caller names (and optionally their parameters)
while(caller.caller && loopCounter < maxLoops) { // <--- there was an error here that I fixed on Oct 15, 2013 @ 11:55AM
callerData += " <- "+((caller.caller.name)?caller.caller.name:"Unnamed Caller:"+getCallerHash(caller.caller))+((_LOG_CALLERARGS_ON)?getCallerArgs(caller.caller.arguments):"")
caller = caller.caller;
loopCounter++;
}
// callerData is now populated with your stack trace.
} else {
// Can't get errors from a non-existent caller
}
}
callerData
變量應填充一串函數名稱(或函數內容的散列,以便您可以半識別它們),可選地使用調用函數的參數。
雖然您不能總是獲取函數名稱,但可以識別這些函數的內容(因為它們應該保持不變),並且您仍然可以從傳遞的參數中獲得有用的調試信息,等等。
注意:我實際上沒有測試上面的代碼,但它應該與我的repo中的代碼大致相同。 如果它不起作用,請參考倉庫並根據您的需要重新計算代碼。 :)
我希望有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.