Ich möchte jeden undefinierten Funktionsfehler abfangen. Gibt es eine globale Fehlerbehandlungsfunktion in JavaScript? Der Anwendungsfall ist das Abfangen von Funktionsaufrufen von Flash, die nicht definiert sind.
Ich möchte jeden undefinierten Funktionsfehler abfangen. Gibt es eine globale Fehlerbehandlungsfunktion in JavaScript? Der Anwendungsfall ist das Abfangen von Funktionsaufrufen von Flash, die nicht definiert sind.
Antworten:
Hilft Ihnen das:
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
Ich bin mir nicht sicher, wie es mit Flash-Fehlern umgeht ...
Update: Es funktioniert nicht in Opera, aber ich hacke gerade Dragonfly, um zu sehen, was es bekommt. Der Vorschlag, Dragonfly zu hacken, ergab sich aus dieser Frage:
window.onerror = function() { alert(42) };
jetzt der Code in der Antwort: window.onerror = function() { alert("Error caught"); };
nicht überschreiben, ich bin immer noch unsicher ..
Weisen Sie das window.onerror
Ereignis einem Ereignishandler wie folgt zu:
<script type="text/javascript">
window.onerror = function(msg, url, line, col, error) {
// Note that col & error are new to the HTML 5 spec and may not be
// supported in every browser. It worked for me in Chrome.
var extra = !col ? '' : '\ncolumn: ' + col;
extra += !error ? '' : '\nerror: ' + error;
// You can view the information in an alert to see things working like this:
alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);
// TODO: Report this error via ajax so you can keep track
// of what pages have JS issues
var suppressErrorAlert = true;
// If you return true, then error alerts (like in older versions of
// Internet Explorer) will be suppressed.
return suppressErrorAlert;
};
</script>
Wie im Code kommentiert, sollte der Browser das Anzeigen eines Warndialogs unterdrücken , wenn der Rückgabewert von window.onerror
ist true
.
Kurz gesagt, das Ereignis wird ausgelöst, wenn entweder 1.) eine nicht erfasste Ausnahme vorliegt oder 2.) ein Kompilierungszeitfehler auftritt.
ungefangene Ausnahmen
- "einige Nachrichten werfen"
- call_something_undefined ();
- cross_origin_iframe.contentWindow.document;, eine Sicherheitsausnahme
Kompilierungsfehler
<script>{</script>
<script>for(;)</script>
<script>"oops</script>
setTimeout("{", 10);
wird versucht, das erste Argument als Skript zu kompilieren
Beispiel für den obigen Fehlercode in Aktion, nachdem dieser zu einer Testseite hinzugefügt wurde:
<script type="text/javascript">
call_something_undefined();
</script>
var error_data = {
url: document.location.href,
};
if(error != null) {
error_data['name'] = error.name; // e.g. ReferenceError
error_data['message'] = error.line;
error_data['stack'] = error.stack;
} else {
error_data['msg'] = msg;
error_data['filename'] = filename;
error_data['line'] = line;
error_data['col'] = col;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/ajax/log_javascript_error');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
console.log('JS error logged');
} else if (xhr.status !== 200) {
console.error('Failed to log JS error.');
console.error(xhr);
console.error(xhr.status);
console.error(xhr.responseText);
}
};
xhr.send(JSON.stringify(error_data));
https://jsfiddle.net/nzfvm44d/
throw
sie manuell erstellt wird. stackoverflow.com/questions/15036165/…
Wenn Ihre Fehlerbehandlung sehr ausgefeilt ist und daher möglicherweise selbst einen Fehler auslöst, ist es hilfreich, ein Flag hinzuzufügen, das angibt, ob Sie sich bereits im "errorHandling-Modus" befinden. Wie so:
var appIsHandlingError = false;
window.onerror = function() {
if (!appIsHandlingError) {
appIsHandlingError = true;
handleError();
}
};
function handleError() {
// graceful error handling
// if successful: appIsHandlingError = false;
}
Andernfalls könnten Sie sich in einer Endlosschleife befinden.
handleError
Methode.
Probieren Sie Atatus aus , das erweiterte Fehlerverfolgung und Überwachung realer Benutzer für moderne Webanwendungen bietet.
Lassen Sie mich erklären, wie Sie Stacktraces erhalten, die in allen Browsern einigermaßen vollständig sind.
Modern Chrome und Opera unterstützen die HTML 5-Entwurfsspezifikation für ErrorEvent und vollständig window.onerror
. In beiden Browsern können Sie window.onerror
das Fehlerereignis entweder ordnungsgemäß verwenden oder ordnungsgemäß binden:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Leider gibt es Firefox, Safari und IE immer noch und wir müssen sie auch unterstützen. Da der Stacktrace in nicht verfügbar ist, müssen window.onerror
wir etwas mehr arbeiten.
Es stellt sich heraus, dass das einzige, was wir tun können, um Stacktraces von Fehlern zu erhalten, darin besteht, unseren gesamten Code in einen try{ }catch(e){ }
Block zu packen und dann zu betrachten e.stack
. Wir können den Prozess mit einer Funktion namens wrap etwas vereinfachen, die eine Funktion übernimmt und eine neue Funktion mit guter Fehlerbehandlung zurückgibt.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
Das funktioniert. Jede Funktion, die Sie manuell umbrechen, hat eine gute Fehlerbehandlung, aber es stellt sich heraus, dass wir sie in den meisten Fällen automatisch für Sie erledigen können.
Indem Sie die globale Definition von addEventListener
so ändern , dass der Rückruf automatisch umbrochen wird, können wir den try{ }catch(e){ }
größten Teil des Codes automatisch einfügen . Auf diese Weise kann vorhandener Code weiterarbeiten, es wird jedoch eine qualitativ hochwertige Ausnahmeverfolgung hinzugefügt.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
Wir müssen auch sicherstellen, dass removeEventListener
das weiter funktioniert. Im Moment wird es nicht, weil das Argument zu addEventListener
geändert wird. Wieder müssen wir dies nur am prototype
Objekt beheben :
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Sie können Fehlerdaten mithilfe des Image-Tags wie folgt senden
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
Haftungsausschluss: Ich bin ein Webentwickler unter https://www.atatus.com/ .
http://yourserver.com
) schreiben , um es zu empfangen und zu speichern. Wenn Sie sich für atatus.com entscheiden , müssen Sie nichts tun. Fügen Sie Ihrer Seite einfach zwei Skriptzeilen hinzu.
Es scheint, dass window.onerror
dies nicht den Zugriff auf alle möglichen Fehler ermöglicht. Insbesondere ignoriert es:
<img>
Ladefehler (Antwort> = 400).<script>
Ladefehler (Antwort> = 400).window.onerror
auf unbekannte Weise manipulieren (Abfrage, Winkel usw.).Hier ist der Beginn eines Skripts, das viele dieser Fehler abfängt, damit Sie Ihrer App während der Entwicklung ein robusteres Debugging hinzufügen können.
(function(){
/**
* Capture error data for debugging in web console.
*/
var captures = [];
/**
* Wait until `window.onload`, so any external scripts
* you might load have a chance to set their own error handlers,
* which we don't want to override.
*/
window.addEventListener('load', onload);
/**
* Custom global function to standardize
* window.onerror so it works like you'd think.
*
* @see http://www.quirksmode.org/dom/events/error.html
*/
window.onanyerror = window.onanyerror || onanyerrorx;
/**
* Hook up all error handlers after window loads.
*/
function onload() {
handleGlobal();
handleXMLHttp();
handleImage();
handleScript();
handleEvents();
}
/**
* Handle global window events.
*/
function handleGlobal() {
var onerrorx = window.onerror;
window.addEventListener('error', onerror);
function onerror(msg, url, line, col, error) {
window.onanyerror.apply(this, arguments);
if (onerrorx) return onerrorx.apply(null, arguments);
}
}
/**
* Handle ajax request errors.
*/
function handleXMLHttp() {
var sendx = XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.send = function(){
handleAsync(this);
return sendx.apply(this, arguments);
};
}
/**
* Handle image errors.
*/
function handleImage() {
var ImageOriginal = window.Image;
window.Image = ImageOverride;
/**
* New `Image` constructor. Might cause some problems,
* but not sure yet. This is at least a start, and works on chrome.
*/
function ImageOverride() {
var img = new ImageOriginal;
onnext(function(){ handleAsync(img); });
return img;
}
}
/**
* Handle script errors.
*/
function handleScript() {
var HTMLScriptElementOriginal = window.HTMLScriptElement;
window.HTMLScriptElement = HTMLScriptElementOverride;
/**
* New `HTMLScriptElement` constructor.
*
* Allows us to globally override onload.
* Not ideal to override stuff, but it helps with debugging.
*/
function HTMLScriptElementOverride() {
var script = new HTMLScriptElement;
onnext(function(){ handleAsync(script); });
return script;
}
}
/**
* Handle errors in events.
*
* @see http://stackoverflow.com/questions/951791/javascript-global-error-handling/31750604#31750604
*/
function handleEvents() {
var addEventListenerx = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = addEventListener;
var removeEventListenerx = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = removeEventListener;
function addEventListener(event, handler, bubble) {
var handlerx = wrap(handler);
return addEventListenerx.call(this, event, handlerx, bubble);
}
function removeEventListener(event, handler, bubble) {
handler = handler._witherror || handler;
removeEventListenerx.call(this, event, handler, bubble);
}
function wrap(fn) {
fn._witherror = witherror;
function witherror() {
try {
fn.apply(this, arguments);
} catch(e) {
window.onanyerror.apply(this, e);
throw e;
}
}
return fn;
}
}
/**
* Handle image/ajax request errors generically.
*/
function handleAsync(obj) {
var onerrorx = obj.onerror;
obj.onerror = onerror;
var onabortx = obj.onabort;
obj.onabort = onabort;
var onloadx = obj.onload;
obj.onload = onload;
/**
* Handle `onerror`.
*/
function onerror(error) {
window.onanyerror.call(this, error);
if (onerrorx) return onerrorx.apply(this, arguments);
};
/**
* Handle `onabort`.
*/
function onabort(error) {
window.onanyerror.call(this, error);
if (onabortx) return onabortx.apply(this, arguments);
};
/**
* Handle `onload`.
*
* For images, you can get a 403 response error,
* but this isn't triggered as a global on error.
* This sort of standardizes it.
*
* "there is no way to get the HTTP status from a
* request made by an img tag in JavaScript."
* @see http://stackoverflow.com/questions/8108636/how-to-get-http-status-code-of-img-tags/8108646#8108646
*/
function onload(request) {
if (request.status && request.status >= 400) {
window.onanyerror.call(this, request);
}
if (onloadx) return onloadx.apply(this, arguments);
}
}
/**
* Generic error handler.
*
* This shows the basic implementation,
* which you could override in your app.
*/
function onanyerrorx(entity) {
var display = entity;
// ajax request
if (entity instanceof XMLHttpRequest) {
// 400: http://example.com/image.png
display = entity.status + ' ' + entity.responseURL;
} else if (entity instanceof Event) {
// global window events, or image events
var target = entity.currentTarget;
display = target;
} else {
// not sure if there are others
}
capture(entity);
console.log('[onanyerror]', display, entity);
}
/**
* Capture stuff for debugging purposes.
*
* Keep them in memory so you can reference them
* in the chrome debugger as `onanyerror0` up to `onanyerror99`.
*/
function capture(entity) {
captures.push(entity);
if (captures.length > 100) captures.unshift();
// keep the last ones around
var i = captures.length;
while (--i) {
var x = captures[i];
window['onanyerror' + i] = x;
}
}
/**
* Wait til next code execution cycle as fast as possible.
*/
function onnext(fn) {
setTimeout(fn, 0);
}
})();
Es könnte so verwendet werden:
window.onanyerror = function(entity){
console.log('some error', entity);
};
Das vollständige Skript verfügt über eine Standardimplementierung, die versucht, eine halb lesbare "Anzeige" -Version der empfangenen Entität / des empfangenen Fehlers auszudrucken. Kann als Inspiration für einen App-spezifischen Fehlerbehandler verwendet werden. Die Standardimplementierung enthält auch einen Verweis auf die letzten 100 Fehlerentitäten, sodass Sie sie in der Webkonsole überprüfen können, nachdem sie wie folgt aufgetreten sind:
window.onanyerror0
window.onanyerror1
...
window.onanyerror99
Hinweis: Dies funktioniert durch Überschreiben von Methoden für mehrere Browser / native Konstruktoren. Dies kann unbeabsichtigte Nebenwirkungen haben. Es war jedoch nützlich, während der Entwicklung zu verwenden, um herauszufinden, wo Fehler auftreten, Protokolle an Dienste wie NewRelic oder Sentry während der Entwicklung zu senden, damit wir Fehler während der Entwicklung messen können, und beim Staging, um zu debuggen, was gerade passiert eine tiefere Ebene. Es kann dann in der Produktion ausgeschaltet werden.
Hoffe das hilft.
Man sollte auch den zuvor zugeordneten Fehlerrückruf beibehalten
<script type="text/javascript">
(function() {
var errorCallback = window.onerror;
window.onerror = function () {
// handle error condition
errorCallback && errorCallback.apply(this, arguments);
};
})();
</script>
Wenn Sie eine einheitliche Methode suchen, um sowohl nicht erfasste Fehler als auch nicht behandelte Ablehnungen von Versprechungen zu behandeln, können Sie sich die nicht erfasste Bibliothek ansehen .
BEARBEITEN
<script type="text/javascript" src=".../uncaught/lib/index.js"></script>
<script type="text/javascript">
uncaught.start();
uncaught.addListener(function (error) {
console.log('Uncaught error or rejection: ', error.message);
});
</script>
Es hört Fenster. unbehandelte Ablehnung zusätzlich zu window.onerror.
Ich würde empfehlen, Trackjs auszuprobieren.
Es ist eine Fehlerprotokollierung als Dienst.
Es ist erstaunlich einfach einzurichten. Fügen Sie einfach eine <script> -Zeile zu jeder Seite hinzu und fertig. Dies bedeutet auch, dass es erstaunlich einfach zu entfernen ist, wenn Sie entscheiden, dass es Ihnen nicht gefällt.
Es gibt andere Dienste wie Sentry (Open Source, wenn Sie Ihren eigenen Server hosten können), aber es macht nicht das, was Trackjs macht. Trackjs zeichnet die Interaktion des Benutzers zwischen seinem Browser und Ihrem Webserver auf, sodass Sie die Benutzerschritte, die zu dem Fehler geführt haben, tatsächlich verfolgen können, anstatt nur eine Datei- und Zeilennummernreferenz (und möglicherweise eine Stapelverfolgung).
Sie hören das Ereignis onerror ab, indem Sie window.onerror eine Funktion zuweisen:
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 {
alert(msg, url, lineNo, columnNo, error);
}
return false;
};