Jakie są najlepsze praktyki dotyczące obsługi błędów JavaScript?


140

Szukam, aby zacząć moje JavaScript nieco więcej dowodów błędzie, a ja znaleźć mnóstwo dokumentacji na temat korzystania try, catch, finally, i throw, ale nie jestem znalezieniem mnóstwo porad od ekspertów na kiedy i gdzie wrzucić błędów.

  • Czy każdy fragment kodu powinien być zawinięty w try / catch?
  • Czy jest więcej porad na temat tego, w którym momencie należy wykryć błędy?
  • Czy istnieją wady zgłaszania błędów zamiast cichej awarii kodu podczas produkcji?
  • Zostało to poruszone w SO, jeśli chodzi o implementacje, ale czy błędy JS logowania na serwerze są skuteczną strategią?
  • Czy jest jeszcze coś, co powinienem wiedzieć na temat przechwytywania błędów w mojej aplikacji?

Jestem też całkowicie fanatykiem słuchania książek, które mają świetne rozdziały lub szczegółowe wyjaśnienia dotyczące obsługi błędów. Elokwentny JavaScript porusza tę kwestię, ale nie jest zbyt nakazowy ani opiniotwórczy na ten temat.

Dziękuję za wszelkie rady, których możesz udzielić!


Z pewnością zależy to od tego, jak spektakularnie ponosisz porażkę, jeśli coś pójdzie nie tak, i ilości możliwych komunikatów o błędach. Nie chcesz zawieść, ponieważ katalog logowania błędów jest teraz pełny, prawda? - Czy w ogóle tu patrzyłeś? stackoverflow.com/search?q=error+logging+javascript
mplungjan

@mplungjan - przejrzałem tam odpowiedzi, ale niewiele z nich wydawało się kanonicznych, a wyszukiwania najlepszych praktyk obsługi błędów / wyjątków w Javascript nic nie dały, więc pomyślałem, że warto spróbować i poprosić o skondensowane myśli, zarówno dla mojego własne zrozumienie i przyszli poszukiwacze. Być może jest to temat, w którym przepisywanie najlepszych praktyk jest niemożliwe, ale każda sytuacja jest wyjątkowa?
Joshua Cody

1
„Czy każdy fragment kodu powinien być opakowany w try / catch?” Oczywiście nie. Jest mnóstwo kodu, o którym wiesz, że zawsze będzie działać (zakładając oczywiście, że go przetestujesz, ale celem try / catch nie jest wyłapywanie ani tuszowanie błędów kodowania). Tylko zawijaj kod, który może zawieść przez jakiś czas z powodu czegoś poza jego kontrolą, ogólnie rzecz biorąc, takie jak dostęp do zasobów itp. Uwaga: niektóre rzeczy, które mogą zawieść, mają wbudowaną obsługę błędów, np. Nie zawracałbym sobie głowy kodowaniem Ajax od zera, gdy istnieje wiele bibliotek, które to robią, które obsługują problemy z różnymi przeglądarkami i pozwalają określić funkcję obsługi błędów.
nnnnnn

1
To jest dobre pytanie Josh, +1. Mnóstwo rad syntaktycznych, ale jak mówisz, to najłatwiejsza część. Jest to poruszone w odpowiedzi na to pytanie ( stackoverflow.com/questions/2825427/… ), gdzie wyjaśniono, że wyjątki nie są tak często używane w JS i podano ich powody.
whitneyland

Odpowiedzi:


64

Niezwykle interesujący zestaw slajdów na temat obsługi błędów języka JavaScript w przedsiębiorstwie można znaleźć pod adresem http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/

W skrócie podsumowuje:

  1. Załóżmy, że twój kod się nie powiedzie
  2. Rejestruj błędy na serwerze
  3. Ty, a nie przeglądarka, zajmujesz się błędami
  4. Określ, gdzie mogą wystąpić błędy
  5. Wyrzuć własne błędy
  6. Rozróżnij błędy krytyczne i niekrytyczne
  7. Zapewnij tryb debugowania

Slajdy są znacznie bardziej szczegółowe i najprawdopodobniej wskażą ci jakiś kierunek.

AKTUALIZACJA

Wspomnianą powyżej prezentację można znaleźć tutaj: http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation


25
Link devhands jest uszkodzony.
Ryan Gates

7
Tym, którzy czytają to w 2017 roku, twierdzę, że slajdy nie przyniosą zbyt dużej wartości - to podsumowanie dostarcza 90% informacji. To wciąż cenna informacja. Twoje zdrowie!
Philippe Hebert

29

Nicholas Zakas z Yahoo! fame wygłosił referat na temat Enterprise Error Handling ( slajdy ) na Ajax Experience 2008, w którym zaproponował coś takiego:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

Rok później Nicholas Zakas opublikował na swoim blogu aktualizację, która zawierała sprytny wzorzec automatycznego wstrzykiwania kodu obsługi błędów do środowiska produkcyjnego (przy użyciu programowania aspektowego).

Kiedy zaczniesz rejestrować wywołania window.error, zauważysz dwie rzeczy:

  1. Jeśli Twoja witryna jest dość złożona, zarejestrujesz wiele błędów
  2. W wiadomościach undefined: 0 zobaczysz kilka bezużytecznych „window.error”

Zmniejszenie ilości torrentów we wpisach dziennika jest tak proste, jak sprawdzenie ważności i / lub losowej liczby przed zalogowaniem się na serwer:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

Obsługa bezużytecznych błędów „window.error w undefined: 0” zależy od architektury witryny, ale można spróbować zidentyfikować wszystkie wywołania Ajax i zgłosić wyjątek, gdy coś się nie powiedzie (prawdopodobnie zwrócenie śladu stosu za pomocą stacktrace.js ).


69
Wiem, że to stare pytanie, ale sugerowanie przypadkowego ignorowania niektórych błędów jest jednym z najgorszych pomysłów, jakie kiedykolwiek słyszałem.
jbabey

27
@jbabey: W przypadku małej witryny masz rację, ale jeśli prowadzisz dużą witrynę ze 100 000 lub milionami użytkowników, naprawdę nie musisz zalewać serwerów (lub Internetu) zbędnymi żądaniami logowania. W wystarczająco dużym systemie każdy prawdziwy błąd będzie występował dziesiątki tysięcy razy dziennie, więc ta forma ograniczania działa dobrze. Pomysł jest faktycznie realizowany na Facebooku.
Jens Roland

1
Rejestrowanie błędów w trybie debugowania jest prawdopodobnie tak samo ważne, jak ograniczanie raportów o błędach produkcyjnych, więc można zauważyć, że potrzebne jest rozwiązanie do zarządzania tą wartością ograniczające próg rejestrowania.
frattaro

2
@NickBull W latach 2011-2012 przeprojektowałem kilka modułów JavaScript Facebooka; tam to znalazłem.
Jens Roland

1
@NickBull właśnie sprawdził moje stare pliki, nadal je mam. Znalazłem ten trick w module bootloadera Facebooku: if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {(co prawda, że kod nie przepustnica wszystkich błędów, tylko konkretnej klasy błędów timeout)
Jens Roland

8

IHMO, powinieneś używać obsługi błędów w javascript, tak jak robisz to w kilku innych językach (AFAIK: Python, Java).

Aby uzyskać lepszą czytelność (i prawdopodobnie lepszą wydajność, chociaż nie jestem pewien, czy ma to naprawdę duży wpływ), powinieneś używać bloku try / catch głównie w następujących przypadkach:

  • Część kodu, którą chcesz opakować, jest kluczową częścią całego algorytmu . Jeśli się nie powiedzie, może:

    • tworzyć błędy w dalszej części kodów (np. ponieważ brakuje var ...)
    • spraw, aby strona nie wyglądała zgodnie z oczekiwaniami (wpływ na zawartość lub css)
    • sprawiają, że wyniki wyglądają dziwnie dla użytkownika (wpływ na zachowanie kodu)
  • Wiesz, że kod, który piszesz, nie jest kompatybilny z każdą przeglądarką

  • Zaplanowałeś, że kod może się nie powieść (ponieważ nie ma innego sposobu, aby sprawdzić, czy powinien działać, jeśli ... to ... blokuje)
  • A także wtedy, gdy chcesz debugować bez przeszkadzania użytkownikowi końcowemu

W końcu eksperci javascript mogą mieć inne elementy do przekazania.

moje 2 centy do pudełka,

Pozdrowienia,

Maks


2
„Część kodu, którą chcesz opakować, jest kluczową częścią całego algorytmu” - może zależeć od tego, jak chcesz obsłużyć błąd. Jeśli wiesz, że nie ma możliwości kontynuowania algorytmu w przypadku niepowodzenia, lepiej byłoby zawinąć całość w try / catch, ponieważ jeśli twoja metoda try / catch (np.) Jest schowana w zagnieżdżonych pętlach, będzie to bardziej uderzenie w wydajność . Z drugiej strony, jeśli możesz podjąć jakąś akcję w przypadku wyjątku i kontynuować algorytm, będziesz potrzebować bardziej szczegółowej konfiguracji try / catch.
nnnnnn

5

Oprócz innych odpowiedzi: jedną ważną rzeczą jest użycie danych kontekstowych dostępnych w obiektach błędów JavaScript oraz w window.onerrorparametrach funkcji.

Rzeczy takie jak stacktrace (errorObject.stack), nazwa pliku, numer linii i numer kolumny. Pamiętaj, że każda przeglądarka ma pewne różnice ... więc postaraj się, aby uzyskać ładne błędy.

Mogą nawet wystąpić problemy z samym obiektem konsoli . Używam niestandardowej funkcji window.onerror inspirowanej tym i specjalnej funkcji do śledzenia dowolnego obiektu błędu standardowego zainspirowanego tym kodem .

Innym dobrym punktem jest umieszczenie wersji aplikacji internetowej w pobliżu ścieżki stosu (w celu szybkiego i bezpiecznego kopiowania i wklejania). Możesz również wyświetlać błędy bardziej agresywnie (alert ...) w trybie programistycznym, ponieważ programiści nie będą stale monitorować konsoli przeglądarki i mogą nie widzieć niektórych problemów.

Używaj także unikaj używania throw 'My message', używaj throw new Error('My message'), możesz nawet mieć niestandardowe błędy, przeczytaj ten artykuł .

Zawsze dodawaj kontekst do błędów (wersja, identyfikator obiektu, jakiś niestandardowy komunikat, ...), a także upewnij się, że rozróżniasz błędy zewnętrzne (niektóre dane zewnętrzne lub okoliczności, które spowodowały awarię systemu) i błędy wewnętrzne / assertions (twój własny system zawiódł), przeczytaj o „ Projekcie według umowy ”.

Oto przewodnik .

Pomyśl także o użyciu ogólnej obsługi błędów, takiej jak przechwytywacze, biblioteki i frameworki:


0

Stworzyłem do tego skrypt. Blokuje wszystkie polecenia konsoli z wyjątkiem elementów wymienionych na liście dozwolonych lub blokuje wszystko na liście bloków. Działa dobrze nawet z kolorowymi dziennikami konsoli.

https://github.com/iiic/consoleFilter.js

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.