Jaka jest najlepsza technika wychwytywania WSZYSTKICH wyjątków generowanych w JavaScript?
Oczywiście najlepszą techniką jest użycie try ... catch. Ale w przypadku oddzwaniania asynchronicznego i tak dalej może to być trudne.
Wiem, że przeglądarki IE i Gecko obsługują window.onerror, ale co z Operą i Safari?
Oto kilka przypadków testowych, dla których chciałbym mieć centralne rozwiązanie do obsługi wyjątków:
// ErrorHandler-Test1
var test = null;
test.arg = 5;
// ErrorHandler-Test2
throw (new Error("Hello"));
// ErrorHandler-Test3
throw "Hello again";
// ErrorHandler-Test4
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
// ErrorHandler-Test5
try {
var test2 = null;
test2.arg = 5;
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test6
try {
throw (new Error("Goodbye"));
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test7
try {
throw "Goodbye again";
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test8
try {
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
} catch(e) {
ErrorHandler.handleError(e);
}
Jeśli myślisz o innych przypadkach testowych, wspomnij o nich. Kilka z tych przypadków wspomina o metodzie ErrorHandler.handleError. To tylko sugerowana wskazówka podczas korzystania z try ... catch.
javascript
exception
harley.333
źródło
źródło
window.onerror
zaginięcie jest problemem od 2003 roku , ale wygląda na to, że w końcu został rozwiązany . Oczywiście Opera pozostanie uparta.Odpowiedzi:
Jeśli używasz biblioteki takiej jak jQuery do przypisywania wszystkich programów obsługi zdarzeń, możesz użyć kombinacji
window.onerror
i zawinąć kod modułu obsługi zdarzeń jQuery i gotową funkcję funkcją obsługi błędów (zobacz: Śledzenie błędów JavaScript: Dlaczego window.onerror Is Not Enough ).window.onerror
: przechwytuje wszystkie błędy w IE (i większość błędów w Firefoksie), ale nic nie robi w Safari i Opera.źródło
onerror
podejście do obsługi w Safari + Chrome i wydaje się, że działa poprawnie.Wydaje się, że WebKit (Safari, Chrome itp.) Obsługuje teraz
onerror
.Oryginalny post: O ile wiem, WebKit / Safari nie obsługuje
onerror
wydarzenia. Co jest cholernym wstydem.źródło
Właściwie podejście jquery nie jest takie złe. Widzieć:
http://docs.jquery.com/Events/error#fn
i:
$(window).error(function(msg, url, line){ $.post("js_error_log.php", { msg: msg, url: url, line: line }); });
źródło
Złap wszystkie wyjątki za pomocą własnej obsługi wyjątków i użyj instanceof.
$("inuput").live({ click : function (event) { try { if (somethingGoesWrong) { throw new MyException(); } } catch (Exception) { new MyExceptionHandler(Exception); } } }); function MyExceptionHandler(Exception) { if (Exception instanceof TypeError || Exception instanceof ReferenceError || Exception instanceof RangeError || Exception instanceof SyntaxError || Exception instanceof URIError ) { throw Exception; // native error } else { // handle exception } }
MyExcetpionHandler zgłosi błąd natywny, ponieważ nie ma bloku try-catch.
Odwiedź http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
źródło
try-catch
nie zawsze jest najlepszym rozwiązaniem. Na przykład w Chrome 7.0 tracisz ładny ślad stosu w oknie konsoli. Ponowne zgłoszenie wyjątku nie pomaga. Nie znam żadnego rozwiązania, które zachowuje ślady stosu i pozwala reagować na wyjątek.źródło
Przy odrobinie pracy możliwe jest uzyskanie śladów stosu, które są w miarę kompletne we wszystkich przeglądarkach.
Nowoczesne Chrome i Opera (czyli wszystko oparte na silniku renderującym Blink) w pełni obsługują wersję roboczą specyfikacji HTML 5 dla ErrorEvent i
window.onerror
. W obu tych przeglądarkach możeszwindow.onerror
poprawnie użyć lub (zadziwiająco!) Powiązać ze zdarzeniem „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 // sendData(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 // sendData(data); })
Niestety Firefox, Safari i IE są nadal dostępne i musimy je również wspierać. Ponieważ śledzenie stosu nie jest dostępne w programie,
window.onerror
musimy wykonać trochę więcej pracy.Okazuje się, że jedyną rzeczą, jaką możemy zrobić, aby uzyskać ślady stosu z błędów, jest zawinięcie całego kodu w plik
try{ }catch(e){ }
blok, a następnie sprawdzenie pliku e.stack. Możemy nieco uprościć ten proces za pomocą funkcji zwanej wrap, która pobiera 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 // sendData(data); throw e; } } } return func._wrapped; };
To działa. Każda funkcja, którą zawiniesz ręcznie, będzie miała dobrą obsługę błędów.
Możesz wysyłać dane za pomocą znacznika obrazu w następujący sposób
function sendData(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; }
Jednak musisz zrobić zaplecze, aby zebrać dane i front-end, aby zwizualizować dane.
W Atatus pracujemy nad rozwiązaniem tego problemu. Atatus to nie tylko śledzenie błędów, ale także monitorowanie rzeczywistych użytkowników.
Zastrzeżenie: jestem programistą internetowym w Atatus.
źródło
Prawdą jest, że w nowoczesnych przeglądarkach podpięcie window.onerror pod kątem błędów, które pojawiają się na samej górze, wraz z dodaniem modułów obsługi zdarzeń jQuery dla błędów Ajax, wyłapuje praktycznie wszystkie obiekty Error wrzucane do kodu klienta. Jeśli ręcznie konfigurujesz program obsługi dla window.onerror, w nowoczesnych przeglądarkach odbywa się to
window.addEventListener('error', callback)
, podczas gdy w IE8 / 9 musisz wywołaćwindow.attachEvent('onerror', callback)
.Zauważ, że powinieneś następnie rozważyć środowisko, w którym te błędy są obsługiwane, i powód tego. Wyłapywanie jak największej liczby błędów za pomocą ich śledzenia stosu to jedno, ale pojawienie się nowoczesnych narzędzi programistycznych F12 rozwiązuje ten przypadek użycia podczas lokalnego wdrażania i debugowania. Punkty przerwania itp. Dają więcej danych niż są dostępne w programach obsługi, szczególnie w przypadku błędów zgłaszanych przez biblioteki innych firm, które zostały załadowane z żądań CORS. Musisz podjąć dodatkowe kroki, aby poinstruować przeglądarkę, aby udostępniła te dane.
Kluczowym problemem jest dostarczenie tych danych w środowisku produkcyjnym, ponieważ Twoi użytkownicy mają gwarancję, że będą uruchamiać znacznie szerszą gamę przeglądarek i wersji, niż możesz przetestować, a Twoja witryna / aplikacja będzie się łamać w nieoczekiwany sposób, niezależnie od tego, ile kontroli jakości rzucisz to.
Aby sobie z tym poradzić, potrzebujesz narzędzia do śledzenia błędów produkcyjnych, które wychwytuje każdy błąd zgłaszany w przeglądarkach użytkownika, gdy używają Twojego kodu, i wysyła je do punktu końcowego, gdzie dane mogą być przeglądane przez Ciebie i używane do naprawiania błędów w miarę ich występowania . W Raygun (zrzeczenie się: pracuję w Raygun) włożyliśmy sporo wysiłku, aby zapewnić doskonałe wrażenia, ponieważ istnieje wiele pułapek i problemów, które należy wziąć pod uwagę, których naiwna implementacja zostanie pominięta.
Na przykład jest szansa, że będziesz łączyć i minimalizować swoje zasoby JS, co oznacza, że błędy wyrzucane ze zminimalizowanego kodu będą zawierały niepotrzebne ślady stosu z zniekształconymi nazwami zmiennych. W tym celu potrzebujesz narzędzia do kompilacji do generowania map źródłowych (zalecamy UglifyJS2 dla tej części potoku), a moduł śledzenia błędów do akceptowania i przetwarzania tych map, zmieniając zniekształcone ścieżki stosu z powrotem w czytelne dla człowieka. Raygun robi to wszystko po wyjęciu z pudełka i zawiera punkt końcowy interfejsu API do akceptowania map źródłowych w miarę ich generowania przez proces kompilacji. Jest to kluczowe, ponieważ muszą być niepubliczne, w przeciwnym razie każdy mógłby unieszkodliwić Twój kod, negując jego cel.
Raygun4js biblioteki klienta jest również wyposażony
window.onerror
zarówno dla nowoczesnych i starszych przeglądarek, jak również jQuery haki out-of-the-box, tak aby ustawić to trzeba tylko dodać:<script type="text/javascript" src="//cdn.raygun.io/raygun4js/raygun.min.js" </script> <script> Raygun.init('yourApiKey').attach(); </script>
Istnieje również wiele wbudowanych funkcji, w tym możliwość mutowania ładunku błędu przed jego wysłaniem, dodawanie tagów i niestandardowych danych, metadanych użytkownika, który widział błąd. Eliminuje to również ból związany z uzyskiwaniem dobrych śladów stosu z wyżej wymienionych skryptów CORS innych firm, co rozwiązuje przerażający „błąd skryptu” (który nie zawiera komunikatu o błędzie ani śladu stosu).
Bardziej istotnym problemem jest to, że ze względu na ogromną liczbę odbiorców w sieci witryna wygeneruje wiele tysięcy zduplikowanych wystąpień każdego błędu. Usługa śledzenia błędów, taka jak Raygun, ma sprytne rozwiązania, które pozwalają łączyć je w grupy błędów, dzięki czemu nie utoniesz w zalewie powiadomień i możesz zobaczyć każdy faktyczny błąd gotowy do naprawienia.
źródło
Szukałem również obsługi błędów i śledzenia stosu oraz rejestrowania działań użytkowników. To jest to, co znalazłem, mam nadzieję, że to również pomoże ci https://github.com/jefferyto/glitchjs
źródło