Javascript obsługa błędów. Składnia try-catch-finally. Wyrzucanie błędów.

article-thumbnail

Każde wykonanie instrukcji pozyskującej dane (niezależnie czy jest to odczyt z pliku tekstowego czy z API) obarczony jest ryzykiem wystąpienia błędu. Np. plik może być już otwarty, albo uszkodzony. Wówczas nasz program nie wie co ma zrobić, więc się zawiesza lub wyłącza.

Niemniej programiści opracowali pewne solucje, które mają ten problem rozwiązać. Mowa o metodzie catch() obiektów klasy Promise oraz bloku try…catch(). O ile metody klasy Promise pokrótce już omówiłem we wcześniejszym wpisie, tak o bloku try catch nie było jeszcze mowy.

Kiedy i jak go stosujemy

Oczywiście ten blok zastosujemy tam, gdzie może wystąpić błąd. Do takich miejsc w kodzie zaliczyć musimy wszystkie działania asynchroniczne, a zwłaszcza te korzystające ze składni async/await, gdyż te nie posiadają odpowiednika metody Promise.catch();

Sam blok try catch() podzielmy na trzy mniejsze współgrające ze sobą bloki. Pierwszy z nich to try. Wewnątrz niego umieścimy ryzykowne operacje. Oczywiście granice bloku wyznaczają tzw. wąsy czyli nawiasy klamrowe ( {} ).

Jeżeli podczas wykonywania którejś z nich wystąpi błąd, wówczas wykona się drugi blok catch(). W nawiasie okrągłym przyjmie on obiekt błędu, jaki wystąpił. W natomiast w ciele umieścimy polecenia, które pozwolą nam ten błąd rozpoznać i odpowiednio zareagować (np. zwrócą komunikat o braku zasobu).

Ostatnim blokiem jest opcjonalny (nieobowiązkowy) finally. Wykona się on niezależnie od wystąpienia błędu. Z tego powodu programiści często go pomijają. Zamiast go zapisywać po prostu piszą kolejne linie już poza blokiem. W końcu blok finally nie zajmuje się już wyłapywaniem błędów.

Oto przykładowe wdrożenie tej struktury

<script>
  
  function ryzykownaOperacja()
	{
		throw new Error('Some Error');  
	}

	try
	{
    	let dane = ryzykownaOperacja()
 		document.write('Jeżeli ten komunikat się wyświetli, to znaczy, funkcja nie zwróciła wyjątki');
    }
	catch(err)
    {
    	document.write(err);
    }
	finally
    {
      document.write('<br/> Ten blok wykona się zawsze');
    }
</script>

Wyrzucamy własny błąd

Czasami zajdzie potrzeba, aby funkcja którą piszemy wyrzuciła jakiś wyjątek. Możemy wówczas skorzystać ze słowa kluczowego throw. Po nim należy umieścić krótką informację o błędzie. Dzięki temu w pewien sposób możemy się zabezpieczyć, przed błędnym zaimplementowaniem naszego kodu przez innego programistę ( lub nas samych ). Należy jednak pamiętać że jeżeli funkcja wyrzuci błąd, wówczas przerywa się jej wykonanie. Upraszczając throw działa jak return, z tym że zamiast zwracać wartości funkcji, wyrzuca błąd. Oto przykładowy kod implementujący wyrzucanie błędów.

<script>
  const suma = (a,b) =>
  {
    if(typeof a==='string'||typeof b==='string') throw "Niepoprawny typ argumentu ";
    else return a+b;
  }

  const sumuj = () =>
  {
    const a = document.getElementById('input1').value;
    const b = document.getElementById('input2').value;
    console.log(a,b)
    let wynik;
    try
      {
        wynik = suma(a,b);
      }
    catch(err)
      {
        wynik = err;
      }
    finally
      {
        document.write(`<span color='red'>${wynik}</span> `);
      }
  }
</script>

<style>
  input
  {
    display: block;
    margin-top: 10px;
  }
</style>

<input type='text' id='input1'/>
<input type='text' id='input2'/>
<button onclick='sumuj()'>Sumuj</button>

Jak widać umieściłem funkcję, która może wyrzucić wyjątek, w bloku try…catch(). Dzięki temu uniknąłem sytuacji, w której działanie programu zostałoby zakłócone. Jak widać zmiennej wynik została przypisana wartość komunikatu wyjątku, co wskazuje że do przypisania doszło właśnie w bloku catch().