Chciałbym wyłapać każdy zgłoszony błąd niezdefiniowanej funkcji. Czy w JavaScript jest dostępna funkcja globalnej obsługi błędów? Przypadek użycia przechwytuje wywołania funkcji z pamięci flash, które nie są zdefiniowane.
Chciałbym wyłapać każdy zgłoszony błąd niezdefiniowanej funkcji. Czy w JavaScript jest dostępna funkcja globalnej obsługi błędów? Przypadek użycia przechwytuje wywołania funkcji z pamięci flash, które nie są zdefiniowane.
Odpowiedzi:
Czy to pomaga ci:
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
Nie jestem jednak pewien, jak radzi sobie z błędami Flasha ...
Aktualizacja: nie działa w Operze, ale teraz hakuję Dragonfly, aby zobaczyć, co dostaje. Sugestia dotycząca hakowania Dragonfly pochodzi z tego pytania:
window.onerror = function() { alert(42) };
teraz kod w odpowiedzi: window.onerror = function() { alert("Error caught"); };
nie przesłonięty, wciąż nie jestem pewien ..
Przypisz window.onerror
zdarzenie do procedury obsługi zdarzenia, takiej jak:
<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>
Jak skomentowano w kodzie, jeśli zwróconą wartością window.onerror
jest, true
to przeglądarka powinna ukryć wyświetlanie okna dialogowego z ostrzeżeniem.
W skrócie, zdarzenie jest wywoływane, gdy 1.) wystąpi nieprzechwycony wyjątek lub 2.) wystąpi błąd czasu kompilacji.
nieprzechwycone wyjątki
- rzuć „niektóre wiadomości”
- call_something_undefined ();
- cross_origin_iframe.contentWindow.document ;, wyjątek bezpieczeństwa
błąd kompilacji
<script>{</script>
<script>for(;)</script>
<script>"oops</script>
setTimeout("{", 10);
, spróbuje skompilować pierwszy argument jako skrypt
Przykład powyższego kodu onerror w akcji po dodaniu go do strony testowej:
<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
jest wykonywany ręcznie. stackoverflow.com/questions/15036165/…
Jeśli obsługa błędów jest bardzo wyrafinowana i dlatego może sam wygenerować błąd, przydatne jest dodanie flagi wskazującej, czy użytkownik znajduje się już w „trybie obsługi błędów”. Tak jak:
var appIsHandlingError = false;
window.onerror = function() {
if (!appIsHandlingError) {
appIsHandlingError = true;
handleError();
}
};
function handleError() {
// graceful error handling
// if successful: appIsHandlingError = false;
}
W przeciwnym razie możesz znaleźć się w nieskończonej pętli.
handleError
metody.
Wypróbuj Atatus, który zapewnia zaawansowane śledzenie błędów i monitorowanie rzeczywistych użytkowników w nowoczesnych aplikacjach internetowych.
Pozwól, że wyjaśnię, jak uzyskać ślady stosu, które są w miarę kompletne we wszystkich przeglądarkach.
Nowoczesne Chrome i Opera w pełni obsługują specyfikację wersji roboczej HTML 5 dla ErrorEvent i window.onerror
. W obu tych przeglądarkach można odpowiednio użyć window.onerror
lub powiązać zdarzenie „błąd”:
// 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);
})
Niestety Firefox, Safari i IE są nadal dostępne i my też musimy je wspierać. Ponieważ stacktrace nie jest dostępny wwindow.onerror
musimy wykonać trochę więcej pracy.
Okazuje się, że jedyne, co możemy zrobić, aby uzyskać ślady stosu z błędów, to owinąć cały nasz kod w try{ }catch(e){ }
blok, a następnie spojrzeć e.stack
. Możemy nieco ułatwić ten proces dzięki funkcji o nazwie wrap, która przyjmuje funkcję i zwraca nową funkcję z dobrą obsługą błędów.
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;
};
To działa. Każda funkcja, którą ręcznie zawijasz, będzie dobrze obsługiwać błędy, ale okazuje się, że w większości przypadków możemy to zrobić automatycznie.
Zmieniając globalną definicję addEventListener
tak, aby automatycznie zawijała wywołanie zwrotne, możemy automatycznie wstawiać try{ }catch(e){ }
większość kodu. Dzięki temu istniejący kod nadal działa, ale dodaje wysokiej jakości śledzenie wyjątków.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
Musimy również upewnić się, że removeEventListener
nadal działa. W tej chwili tak się nie stanie, ponieważ argument do addEventListener
został zmieniony. Znów musimy tylko to naprawić na prototype
obiekcie:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Dane o błędach można wysyłać za pomocą znacznika obrazu w następujący sposób
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;
}
Oświadczenie: Jestem programistą internetowym na https://www.atatus.com/ .
http://yourserver.com
), aby odbierać i przechowywać. Jeśli wybierzesz atatus.com , nie musisz nic robić. Wystarczy dołączyć dwie linie skryptu na swojej stronie.
Wygląda na to, że window.onerror
nie zapewnia dostępu do wszystkich możliwych błędów. W szczególności ignoruje:
<img>
błędy ładowania (odpowiedź> = 400).<script>
błędy ładowania (odpowiedź> = 400).window.onerror
w nieznany sposób (jquery, angular, itp.).Oto początek skryptu, który wyłapuje wiele z tych błędów, dzięki czemu możesz dodać bardziej niezawodne debugowanie do swojej aplikacji podczas programowania.
(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);
}
})();
Można go użyć w następujący sposób:
window.onanyerror = function(entity){
console.log('some error', entity);
};
Pełny skrypt ma domyślną implementację, która próbuje wydrukować częściowo czytelną „wyświetlaną” wersję otrzymanego obiektu / błędu. Może być wykorzystany jako inspiracja do obsługi błędów specyficznych dla aplikacji. Domyślna implementacja zachowuje również odwołanie do ostatnich 100 jednostek błędów, dzięki czemu można je sprawdzić w konsoli internetowej po ich wystąpieniu, np .:
window.onanyerror0
window.onanyerror1
...
window.onanyerror99
Uwaga: Działa to poprzez zastąpienie metod w kilku konstruktorach przeglądarki / natywnych. Może to mieć niezamierzone skutki uboczne. Przydało się to jednak podczas programowania, aby dowiedzieć się, gdzie występują błędy, aby wysłać dzienniki do usług takich jak NewRelic lub Sentry podczas programowania, abyśmy mogli mierzyć błędy podczas programowania oraz podczas przemieszczania, abyśmy mogli debugować to, co się dzieje głębszy poziom. Następnie można go wyłączyć w produkcji.
Mam nadzieję że to pomoże.
Należy również zachować wcześniej skojarzone wywołanie zwrotne onerror
<script type="text/javascript">
(function() {
var errorCallback = window.onerror;
window.onerror = function () {
// handle error condition
errorCallback && errorCallback.apply(this, arguments);
};
})();
</script>
Jeśli chcesz ujednoliconego sposobu obsługi zarówno nieprzechwyconych błędów, jak i nieobsługiwanych odrzuceń obietnic, możesz zajrzeć do nieprzechwyconej biblioteki .
EDYTOWAĆ
<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>
Słucha okna. nieobsługiwane odrzucenie oprócz window.onerror.
Polecam wypróbować Trackjs .
To rejestrowanie błędów jako usługa.
Jest niezwykle prosty w konfiguracji. Wystarczy dodać jeden wiersz <script> do każdej strony i to wszystko. Oznacza to również, że będzie niezwykle łatwy do usunięcia, jeśli zdecydujesz, że ci się nie podoba.
Istnieją inne usługi, takie jak Sentry (który jest open-source, jeśli możesz hostować własny serwer), ale nie robi to, co robi Trackjs. Trackjs rejestruje interakcję użytkownika między jego przeglądarką a serwerem WWW, dzięki czemu można faktycznie śledzić kroki użytkownika, które doprowadziły do błędu, w przeciwieństwie do samego odwołania do pliku i numeru linii (i może śledzenia stosu).
Słuchasz zdarzenia onerror, przypisując funkcję do window.onerror:
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;
};