, ,

Wyjątki na przykładzie JS

Błędy w programowaniu to coś normalnego więc praca programisty jest ściśle powiązana z
debugowaniem. W zależności od języka w którym programujemy niektóre typy błędów można wykryć
jeszcze przed samą kompilacją kodu lecz istnieją także takie sytuacje w których błąd uwidacznia się
dopiero w trakcie trwania programu (lub aplikacji). Wyjątek jest właśnie takim typem błędu, przykładem
może być tablica indeksowana od 0 do x-1 używana w pętli od 1 do x – kod się skompiluje (zakładając, że
semantyka jest poprawna) ale przy próbie wykonana takiej pętli dojdzie do odwołania od nieistniejącego
elementu (tab[x]) co spowoduje do rzucenia wyjątku. Tak, wyjątkami się rzuca i powinniśmy je traktować
jako podpowiedź co poszło nie tak w naszej aplikacji. Między różnymi językami są drobne różnice w składni
ale idea pozostaje ta sama.

Omówmy obsługę wyjątków na przykładzie JS’a. Cała “impreza” polega na wykorzystaniu przynajmniej
dwóch z trzech
dostępnych bloków :

try {
  var i = 0;
  i++;
  // tutaj umieszczamy kod który chcemy wykonać,
  // który może ale nie musi rzucić wyjątkiem
  // wyjątki mogą być rzucane "automatycznie"
  // np odwołując się do nieistniejącego obiektu lub funkcji
  // ale mogą być też rzucane przez nas:
  if ( i != 0 ) {
    // za pomocą słowa kluczowego "throw" możemy rzucić własny wyjątek
    // przekazując rzucany obiekt
    throw "i jest różne od zera!"; // więcej o rzucanych obiektach w dalszej części wpisu
  }
} catch( error ) {
  // to jest blok łapiący wyjątek - jego kod wykona się TYLKO I WYŁĄCZNIE jeśli
  // w bloku "try" został rzucony wyjątek
  // w zmiennej "error" będziemy mieli rzucony obiekt
  // na podstawie którego możemy podejmować dalsze decyzje
} finally {
  // jedyny nieobowiązkowy blok, jeśli istnieje jego kod wykona się ZAWSZE
  // niezależnie czy został rzucony wyjątek czy nie
}Code language: JavaScript (javascript)

Można by powiedzieć fajnie, że jest taki bajer ale po co mi on? Najprostszym przykładem
“po co” może być sytuacja z którą spotkał się zapewne każdy z nas – wrzucamy edytowane przez nas
skrypty na stronę i nagle połowa rzeczy przestaje działać a w konsoli pełno błędów. Dlaczego tak się
stało? Moim zdaniem lepiej będzie odpowiedzieć na pytanie co się dzieje jeśli wyjątek jest rzucany? Otóż w
takim przypadku dalszy kod (czyli ten znajdujący się poniżej miejsca w którym został rzucony) nie zostaje
wykonany a zamiast tego przechodzimy do najbliższego bloku catch czyli jeśli na samym początku
naszego skryptu wystąpi jakiś wyjątek dalsza część się po prostu nie wykona.

Wspominałem już o rzucanych obiektach i o tym, że robimy to za pomocą throw, powiedzmy sobie teraz
kilka słów właśnie o tym. Domyślnie mamy wbudowanych kilka klas którymi możemy rzucać np klasa
Error której obiekt możemy stworzyć dwojako:

const x = Error( 'Jestem stworzony przy pomocy wyowałania funkcji!' );
// ma te samą funkcję jak to:
const y = new Error( 'Jestem stworzony przy pomocy słowa kluczowego "new"!' );
throw x; // rzucamy wyjątekCode language: JavaScript (javascript)

Więcej informacji na temat tej oraz “siostrzanych” klas możecie znaleźć np. tutaj. Jak już widzieliście na
samym początku nie jesteśmy ograniczeni tylko do tych klas. Rzucić możemy jakimkolwiek obiektem –
nawet zwykłem tekstem throw „rzucam stringiem!”;, pozostaje tylko kwestia późniejszego
odpowiedniego obsłużenia wyjątku bo jeśli odwołamy się do nieistniejącej metody lub pola spowoduje to
rzucenie kolejnego wyjątku.

Skoro wiemy (mniej lub bardziej) czym wyjątki są uświadommy sobie teraz kolejną ważną rzecz dla JS’a
czyli kolejkowanie zadań oraz istnienie tzw. stosu. Wystąpienie wyjątku powoduje przerwanie aktualnie
wykonywanego zadania (czyli wszystkiego co aktualnie jest na stosie) ale nie blokuje to następnych
zakolejkowanych zadań, np. jeśli podczas obsługi eventu click rzucimy wyjątkiem to będzie on rzucany za
każdym kliknięciem. Więcej o kolejce zadań i stosie możecie posłuchać w tej prezentacji.
Dla zrozumienia problemu zapoznajcie się z tym kodem.

Podsumowując, wyjątki i ich obsługa jeśli wykorzystana świadomy w odpowiedni sposób może być naszym
przyjacielem.


Po napisaniu tego wpisu nasz CTO podrzucił słuszną uwagę, że od ES2019 możemy używać skróconego bloku try-catch (bez specyfikowania zmiennej e/error):

try {
  request = JSON.parse(rawRequest);
} catch {
  alert('Request was malformed');
}Code language: JavaScript (javascript)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

Nasza pasja do technologii nie kończy się na dostarczaniu wnikliwych treści poprzez ten blog. Zapraszamy po więcej tajników specjalistycznej wiedzy dla entuzjastów takich jak Ty.

Tematy

animacje animate Attribute inheritance Block Theme Branża IT bug Code Comments CSS CSS Flexbox developer tools Doc Blocks dostępność www Edge Edge computing Editor Flex Gap FSE Full Site Editing GIT GIT Submodules Gutenberg HTTP HTTP/2 HTTP/3 IT JS Memcached Optimization plik SVG Praca praca w IT Rozmowy o WordPress strony www SVG Text-overflow theme.json v-model Vue.js wcag web accessibility Web development webkit line clamp Wordpress wp postmeta api wp transient