Skip to content

9. Błędy i wyjątki

Image

Javascript nie posiada zbyt zaawansowanego systemu wyjątków. Oferuje jednak instrukcję [throw], która pozwala zgłosić błąd, a także strukturę try / catch / finally, która umożliwia przechwytywanie tych błędów.

9.1. Skrypt [excep-01]

W poniższym skrypcie wyświetlimy bieżącą datę w formacie [heures:minutes:secondes:millisecondes]. W tym celu wykorzystamy bibliotekę jS o nazwie [moment.js]. Instalujemy ją, jak zwykle, za pomocą narzędzia [npm]:

Image

Kod skryptu wygląda następująco:


'use strict';

// pakiet moment
import moment from 'moment';

...

Aby dowiedzieć się, jak zapisać wiersz [import] z wiersza 4, można zapoznać się z definicją modułu [moment]:

Image

  • w [1-2] przechodzimy do definicji modułu;
  • w przypadku [3] mamy plik Typescript, a nie JavaScript. Podczas wykonywania ten plik Typescript jest kompilowany do pliku JavaScript przed użyciem;
  • w [4] szukamy instrukcji [export] (Ctrl-F);
  • w pliku [5] instrukcja eksportuje obiekt [moment]. Obiekt ten można zaimportować do pliku ES6 w następujący sposób:

import moment from 'moment';

Do zaimportowania obiektu [moment] można użyć dowolnej nazwy, na przykład:


import m from 'moment';

Wróćmy do kodu skryptu:


'use strict';

// pakiet moment
import moment from 'moment';

// zasada działania try / catch / finally
for (let i = 0; i < 10; i++) {
  // data i godzina bieżąca
  const now = Date.now();
  // formatowanie czasu w celu uzyskania milisekund
  const time = moment(now).format("HH:mm:ss:SSS");
  // milisekundy
  const milli = Number(time.substr(time.length - 3));
  // wyświetlanie
  console.log("--------------------itération n° ", i, "à", time);
  try {
    // liczba wariantów w zależności od aktualnej godziny
    const nbre = milli % 2;
    if (nbre === 0) {
      // wyświetlenie komunikatu o błędzie
      throw "erreur";
    }
    // jeśli dotarłeś tutaj, oznacza to, że nie wystąpił błąd
    console.log("pas d'erreur");
  } catch (error) {
    // jeśli trafiłeś tutaj, oznacza to, że wystąpił błąd
    console.log("erreur1=", error);
  } finally {
    // wykonane w każdym przypadku, niezależnie od tego, czy wystąpił błąd, czy nie
    console.log("finally")
  }
}

Komentarze

  • wiersz 4: import biblioteki [moment];
  • zasada działania skryptu polega na wykonaniu pętli 10 razy (wiersz 7). W każdym cyklu pętli pobierany jest aktualny czas w formacie [heures:minutes:secondes:millisecondes] (wiersze 8–13);
  • jeśli liczba milisekund jest parzysta, wyświetlany jest komunikat o błędzie (wiersze 19–22);
  • Chodzi tu o zrozumienie działania konstrukcji try / catch / finally

Wykonanie


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-01.js"
--------------------itération n° 0 à 17:57:04:440
erreur1= erreur
finally
--------------------itération n° 1 à 17:57:04:447
pas d'erreur
finally
--------------------itération n° 2 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 3 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 4 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 5 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 6 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 7 à 17:57:04:448
erreur1= erreur
finally
--------------------itération n° 8 à 17:57:04:449
pas d'erreur
finally
--------------------itération n° 9 à 17:57:04:449
pas d'erreur
finally

Widać, że klauzula [finally] jest zawsze wykonywana, niezależnie od tego, czy wystąpił błąd, czy nie.

9.2. skrypt [excep-02]

Ten skrypt, który instrukcja [throw] może uruchomić, może przetwarzać dowolny typ danych, a dane te są w całości pobierane przez klauzulę [catch].


'use strict';

// można „rzucić” (throw) praktycznie cokolwiek, aby zgłosić błąd
let i = 0;
console.log("--------------------essai n° ", i);
// rzucenie ciągu znaków
try {
  throw "msg d'erreur";
} catch (error) {
  // wystąpił błąd
  console.log("erreur=[", error, "], type=", typeof (error));
}
// utworzyć tabelę
i++;
console.log("--------------------essai n° ", i);
try {
  throw [1, 2, 3]
} catch (error) {
  // wystąpił błąd
  console.log("erreur=[", error, "], type=", typeof (error));
}
// uruchomienie obiektu dosłownego
i++;
console.log("--------------------essai n° ", i);
try {
  throw { nom: "hercule", pays: "grèce antique" }
} catch (error) {
  // wystąpił błąd
  console.log("erreur=[", error, "], type=", typeof (error));
}
// wywołanie typu Error
i++;
console.log("--------------------essai n° ", i);
try {
  throw new Error("erreur de connexion au réseau");
} catch (error) {
  // wystąpił błąd
  console.log("erreur=[", error, "], type=", typeof (error));
}
// wywołano typ Error
i++;
console.log("--------------------essai n° ", i);
try {
  throw new Error("erreur de connexion au réseau");
} catch (error) {
  // wystąpił błąd – komunikat znajduje się w [error.message]
  console.log("erreur.message=[", error.message, "], type(error)=", typeof (error));
}

Komentarze

  • wiersze 35, 44: [Error] to klasa JavaScript, której konstruktor przyjmuje jako pierwszy opcjonalny parametr komunikat o błędzie. Komunikat ten można pobrać z właściwości [Error.message] (wiersz 47);
  • istnieją inne klasy oprócz [Error] służące do zgłaszania błędów: [EvalError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError);

Wykonanie


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-02.js"
--------------------essai n° 0
erreur=[ msg d'erreur ], type= string
--------------------essai n° 1
erreur=[ [ 1, 2, 3 ] ], type= object
--------------------essai n° 2
erreur=[ { nom: 'hercule', pays: 'grèce antique' } ], type= object
--------------------essai n° 3
erreur=[ Error: erreur de connexion au réseau
at Object.<anonymous> (c:\Data\st-2019\dev\es6\javascript\exceptions\excep-02.js:35:9)
at Object.<anonymous> (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:251206)
at c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:245054
at Generator.next (<anonymous>)
at bl (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:245412)
at kl (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:247659)
at Object.u (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:287740)
at Object.o (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:287137)
at Object.<anonymous> (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:284879)
at Object.apply (c:\Temp\19-09-01\javascript\node_modules\esm\esm.js:1:199341) ], type= object
--------------------essai n° 4
erreur.message=[ erreur de connexion au réseau ], type(error)= object

9.3. skrypt [excep-03]

Ten skrypt pokazuje, że w pliku [catch] można rozróżnić typ instancji [Error] przechwyconej przez [catch]:


'use strict';

// pakiet moment
import moment from 'moment';

// rozróżnienie instancji klasy Error otrzymanej w [catch]
for (let i = 0; i < 10; i++) {
  // data i godzina bieżącego momentu
  const now = Date.now();
  // formatowanie czasu w celu uzyskania milisekund
  const time = moment(now).format("HH:mm:ss:SSS");
  // milisekundy
  const milli = Number(time.substr(time.length - 3));
  console.log("--------------------itération n° ", i);
  try {
    // liczba [0, 1, 2]
    const nbre = milli % 3;
    switch (nbre) {
      case 0:
        throw new ReferenceError("erreur 1");
      case 1:
        throw new RangeError("erreur 2");
      default:
        throw new EvalError("erreur 3");
    }
  } catch (error) {
    // wystąpił błąd
    if (error instanceof ReferenceError) {
      console.log("ReferenceError :", error.message);
    } else {
      if (error instanceof RangeError) {
        console.log("RangeError :", error.message);
      }
      else {
        if (error instanceof EvalError) {
          console.log("EvalError :", error.message);
        }
      }
    }
  }
}

Wykonanie


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\exceptions\excep-03.js"
--------------------itération n° 0
ReferenceError : erreur 1
--------------------itération n° 1
RangeError : erreur 2
--------------------itération n° 2
RangeError : erreur 2
--------------------itération n° 3
RangeError : erreur 2
--------------------itération n° 4
RangeError : erreur 2
--------------------itération n° 5
RangeError : erreur 2
--------------------itération n° 6
EvalError : erreur 3
--------------------itération n° 7
EvalError : erreur 3
--------------------itération n° 8
EvalError : erreur 3
--------------------itération n° 9
EvalError : erreur 3