Szukaj…


Składnia

  • spróbuj {…} catch (error) {…}
  • spróbuj {…} wreszcie {…}
  • spróbuj {…} złapać (błąd) {…} wreszcie {…}
  • wyślij nowy błąd ([komunikat]);
  • błąd wyrzucenia ([komunikat]);

Uwagi

try pozwala zdefiniować blok kodu, który będzie testowany pod kątem błędów podczas jego wykonywania.

catch pozwala zdefiniować blok kodu do wykonania, jeśli wystąpi błąd w bloku try .

finally pozwala wykonać kod niezależnie od wyniku. Uważaj jednak, instrukcje przepływu bloków try i catch zostaną zawieszone do czasu zakończenia wykonywania bloku ostatecznie.

Interakcja z obietnicami

6

Wyjątkiem jest kod synchroniczny, a odrzucenia - obietnica oparta na kodzie asynchronicznym. Jeśli wyjątek zostanie zgłoszony w module obsługi obietnicy, jego błąd zostanie automatycznie przechwycony i użyty do odrzucenia obietnicy.

Promise.resolve(5)
    .then(result => {
        throw new Error("I don't like five");
    })
    .then(result => {
        console.info("Promise resolved: " + result);
    })
    .catch(error => {
        console.error("Promise rejected: " + error);
    });

Promise rejected: Error: I don't like five
7

Propozycja funkcji asynchronicznych - która ma być częścią ECMAScript 2017 - rozszerza to w przeciwnym kierunku. Jeśli czekasz na odrzuconą obietnicę, jej błąd jest zgłaszany jako wyjątek:

async function main() {
  try {
    await Promise.reject(new Error("Invalid something"));
  } catch (error) {
    console.log("Caught error: " + error);
  }
}
main();

Caught error: Invalid something

Obiekty błędów

Błędy czasu wykonania w JavaScript są instancjami obiektu Error . Obiekt Error może być również używany jako taki lub jako podstawa wyjątków zdefiniowanych przez użytkownika. Możliwe jest wyrzucenie dowolnego typu wartości - na przykład ciągów - ale zdecydowanie zalecamy użycie Error lub jednego z jego pochodnych, aby zapewnić prawidłowe zachowanie informacji debugowania - np. Śladów stosu.

Pierwszym parametrem konstruktora Error jest czytelny dla człowieka komunikat o błędzie. Powinieneś zawsze próbować podać przydatny komunikat o błędzie dotyczący tego, co poszło źle, nawet jeśli dodatkowe informacje można znaleźć gdzie indziej.

try {
   throw new Error('Useful message');
} catch (error) {
   console.log('Something went wrong! ' + error.message);
}

Kolejność operacji i zaawansowane myśli

Bez bloku try catch niezdefiniowane funkcje będą zgłaszać błędy i zatrzymywać wykonywanie:

undefinedFunction("This will not get executed");
console.log("I will never run because of the uncaught error!");

Zgłasza błąd i nie uruchamia drugiej linii:

// Uncaught ReferenceError: undefinedFunction is not defined

Potrzebujesz bloku try catch, podobnego do innych języków, aby upewnić się, że złapałeś ten błąd, aby kod mógł nadal wykonywać:

try {
    undefinedFunction("This will not get executed");
} catch(error) {
    console.log("An error occured!", error);
} finally {
    console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");

Teraz wykryliśmy błąd i możemy być pewni, że nasz kod zostanie wykonany

// An error occured! ReferenceError: undefinedFunction is not defined(…)
// The code-block has finished
// I will run because we caught the error!

Co jeśli wystąpi błąd w naszym bloku catch !?

try {
    undefinedFunction("This will not get executed");
} catch(error) {
    otherUndefinedFunction("Uh oh... ");
    console.log("An error occured!", error);
} finally {
    console.log("The code-block has finished");
}
console.log("I won't run because of the uncaught error in the catch block!");

Nie przetwarzamy reszty naszego bloku catch, a wykonanie zostanie zatrzymane, z wyjątkiem bloku w końcu.

// The code-block has finished
// Uncaught ReferenceError: otherUndefinedFunction is not defined(…)

Zawsze możesz zagnieżdżać bloki try catch. Ale nie powinieneś, bo będzie bardzo bałagan.

try {
    undefinedFunction("This will not get executed");
} catch(error) {
    try {
        otherUndefinedFunction("Uh oh... ");
    } catch(error2) {
        console.log("Too much nesting is bad for my heart and soul...");
    }
    console.log("An error occured!", error);
} finally {
    console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");

Złapie wszystkie błędy z poprzedniego przykładu i zarejestruje następujące:

//Too much nesting is bad for my heart and soul...
//An error occured! ReferenceError: undefinedFunction is not defined(…)
//The code-block has finished
//I will run because we caught the error!

Jak więc wyłapać wszystkie błędy !? Dla niezdefiniowanych zmiennych i funkcji: nie możesz.

Nie powinieneś także zawijać wszystkich zmiennych i funkcji w blok try / catch, ponieważ są to proste przykłady, które pojawią się tylko raz, dopóki ich nie naprawisz. Jednak w przypadku obiektów, funkcji i innych zmiennych, o których wiesz, że istnieją, ale nie wiesz, czy będą istnieć ich właściwości, podprocesy lub skutki uboczne, lub spodziewasz się pewnych stanów błędów w pewnych okolicznościach, powinieneś wyodrębnić obsługę błędów w jakiś sposób. Oto bardzo prosty przykład i wdrożenie.

Bez chronionego sposobu wywoływania metod niezaufanych lub zgłaszania wyjątków:

function foo(a, b, c) {
    console.log(a, b, c);
    throw new Error("custom error!");
}
try {
    foo(1, 2, 3);
} catch(e) { 
    try {
        foo(4, 5, 6); 
    } catch(e2) {
        console.log("We had to nest because there's currently no other way...");
    }
    console.log(e);
}
// 1 2 3
// 4 5 6
// We had to nest because there's currently no other way...
// Error: custom error!(…)

I z ochroną:

function foo(a, b, c) {
    console.log(a, b, c);
    throw new Error("custom error!");
}
function protectedFunction(fn, ...args) {
    try {
        fn.apply(this, args);
    } catch (e) {
        console.log("caught error: " + e.name + " -> " + e.message);
    }
}

protectedFunction(foo, 1, 2, 3);
protectedFunction(foo, 4, 5, 6);

// 1 2 3
// caught error: Error -> custom error!
// 4 5 6
// caught error: Error -> custom error!

Wychwytujemy błędy i nadal przetwarzamy cały oczekiwany kod, choć z nieco inną składnią. Tak czy inaczej, zadziała, ale kiedy budujesz bardziej zaawansowane aplikacje, będziesz chciał zacząć myśleć o sposobach wyodrębnienia obsługi błędów.

Typy błędów

W JavaScript jest sześć konkretnych konstruktorów błędów podstawowych:

  • EvalError - tworzy instancję reprezentującą błąd występujący w odniesieniu do funkcji globalnej eval() .

  • InternalError - tworzy instancję reprezentującą błąd, który występuje, gdy zostanie zgłoszony błąd wewnętrzny w silniku JavaScript. Np. „Za dużo rekurencji”. (Obsługiwany tylko przez Mozilla Firefox )

  • RangeError - tworzy instancję reprezentującą błąd, który występuje, gdy zmienna liczbowa lub parametr jest poza swoim prawidłowym zakresem.

  • ReferenceError - tworzy instancję reprezentującą błąd, który występuje, gdy następuje odwołanie do niepoprawnego odwołania.

  • SyntaxError - tworzy instancję reprezentujący błąd składni, który występuje podczas analizowania kodu w eval() .

  • TypeError - tworzy instancję reprezentującą błąd, który występuje, gdy zmienna lub parametr nie jest poprawnego typu.

  • URIError - tworzy instancję reprezentujący błąd, który występuje, gdy encodeURI() lub decodeURI() przekazywane są nieprawidłowe parametry.

Jeśli wdrażasz mechanizm obsługi błędów, możesz sprawdzić, jaki rodzaj błędu wychwytujesz z kodu.

try {
    throw new TypeError();
}
catch (e){
    if(e instanceof Error){
        console.log('instance of general Error constructor');
    }

    if(e instanceof TypeError) {
        console.log('type error');
    }
}

W takim przypadku e będzie wystąpieniem TypeError . Wszystkie typy błędów rozszerzają podstawowy konstruktor Error , dlatego jest to również instancja Error .

Pamiętając o tym, pokazuje nam, że sprawdzanie e jako wystąpienia Error jest w większości przypadków bezużyteczne.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow