Les erreurs : origine et pourquoi les traiter
Dans le monde du développement et particulièrement du développement Web, il y a toujours une chance que des erreurs se produisent.
Une « erreur » se traduit généralement par un comportement inattendu et non voulu du script. Les erreurs peuvent avoir différentes origines :
- Elles peuvent provenir du développeur dans le cas d’erreur de syntaxe dans le code même ;
- Elles peuvent provenir du serveur dans le cas où celui-ci est dans l’incapacité de fournir les ressources (fichiers) demandés ;
- Elles peuvent provenir du navigateur ;
- Elles peuvent encore être créées par un utilisateur qui envoie une valeur non valide par exemple.
Lorsqu’on crée un site, ou lorsqu’on distribue un script, on essaiera toujours de faire le maximum pour limiter les cas d’erreurs et pour prendre en charge les erreurs éventuelles sur lesquelles on n’a pas le contrôle.
En effet, laisser une erreur dans la nature peut avoir de graves conséquences pour un site : dans le meilleur des cas, l’erreur n’est pas grave et sera ignorée. Dans la majorité des cas, cependant, une erreur va provoquer l’arrêt brutal d’un script et on risque donc d’avoir des codes et des pages non fonctionnelles. Dans le pire des cas, une erreur peut être utilisée comme faille de sécurité par des utilisateurs malveillants qui vont l’utiliser pour dérober des informations ou pour tromper les autres visiteurs.
Heureusement, le JavaScript nous fournit des outils qui nous permettent simplement d’indiquer quoi faire en cas d’erreur.
Dans cette partie, nous allons nous concentrer sur la prise en charge des cas d’erreurs sur lesquels on n’a pas de contrôle direct, c’est-à-dire sur les erreurs générées par le serveur, le navigateur, ou l’utilisateur.
Dans le cas où l’erreur provient d’une erreur de syntaxe dans le script, le procédé est très simple : il suffit de reprendre le script et de corriger l’erreur pour que celui-ci ait une syntaxe valide.
Gérer une erreur avec les blocs try…catch
La première chose qu’il y a à savoir lorsqu’on souhaite prendre en charge les erreurs est que lorsqu’une erreur d’exécution survient dans un script le JavaScript crée automatiquement un objet à partir de l’objet global Error
qui est l’objet de base pour les erreurs en JavaScript.
Nous allons ensuite pouvoir capturer l’objet renvoyé par le JavaScript qui représente l’erreur déclenchée et pouvoir indiquer ce qu’on souhaite en faire.
Pour cela, le JavaScript dispose d’une syntaxe en deux blocs try
et catch
.
Comment ces deux blocs fonctionnent ? Cela va être très simple : nous allons placer le code à tester (celui qui peut potentiellement générer une erreur) au sein de notre bloc try
puis allons capturer l’erreur potentielle dans le bloc catch
et indiquer comment la gérer.
Ici, il se passe en fait la chose suivante : le JavaScript va d’abord tenter d’exécuter le code au sein de notre bloc try
. Si le code s’exécute normalement, alors le boc catch
et les instructions à l’intérieur vont être ignorées. Si en revanche une erreur survient durant l’exécution du code contenu dans try
, alors le bloc catch
sera lu.
Prenons immédiatement quelques exemples simples pour illustrer cela :
See the Pen
Cours JavaScript 11.1.1 by Pierre (@pierregiraud)
on CodePen.
Ici, on place une instruction alert()
dans notre bloc try
. Si aucune erreur n’est rencontrée (ce qui est le cas normalement), la boite d’alerte s’affichera bien avec son message et le bloc catch
sera ignoré.
Essayons maintenant de générer une erreur manuellement pour voir comment le JavaScript se comporte. Dans l’exemple ci-dessous, je vais essayer d’utiliser une variable que je n’ai pas déclarée, ce qui va provoquer une erreur. Bien évidemment, c’est ici une erreur de syntaxe et nous ne devrions pas en pratique prendre en charge ce type d’erreur avec la syntaxe try…catch
mais devrions la corriger dans le script. Cependant, pour l’exemple, j’ai besoin d’une erreur !
See the Pen
Cours JavaScript 11.1.2 by Pierre (@pierregiraud)
on CodePen.
Ici, on essaie d’exécuter notre script sans blocs try
et catch
. Le JavaScript rencontre une erreur durant l’exécution, renvoie un objet Error
et stoppe l’exécution du script. On peut obtenir des informations sur l’erreur en ouvrant la console de notre navigateur.
Testons maintenant avec la syntaxe try…catch
:
See the Pen
Cours JavaScript 11.1.3 by Pierre (@pierregiraud)
on CodePen.
Comme vous pouvez le voir, cette fois-ci, le contenu de notre bloc catch
est bien exécuté. Le JavaScript va alors se fier aux directives données dans ce bloc pour savoir comment gérer l’erreur. Dans le cas présent, on se contente de renvoyer des informations sur l’erreur. Comme on ne demande pas au JavaScript d’arrêter le script, le reste du script est exécuté comme s’il n’y avait pas d’erreur.
Procéder comme cela nous permet donc de prendre en charge une partie du code à problème sans impacter le reste du script.
Ici, vous pouvez noter qu’on passe un argument err
à catch
. Celui-ci représente l’objet erreur créé par le JavaScript lorsque l’erreur survient et qu’on va « capturer » (catch) pour en utiliser les propriétés.
En effet, le constructeur Error
possède des propriétés standards qu’on va pouvoir utiliser et qui vont nous donner des informations sur l’erreur comme la propriété message
qui contient le message de l’erreur ou name
qui contient le nom de l’erreur.
Vous pouvez noter par ailleurs pour être tout à fait exhaustif qu’en plus du constructeur générique Error
il existe 7 autres constructeurs d’erreurs de base en JavaScript. Selon le type d’erreur, on pourra donc également avoir accès aux méthodes et propriétés de l’un ou de l’autre constructeur. En plus de cela, le DOM nous fournit également une interface de gestion d’erreurs liées à celui-ci : l’interface DOMException
.
Les exceptions en JavaScript et l’instruction throw
Parfois, on va savoir à l’avance que notre code va provoquer des erreurs dans certains cas particuliers d’utilisation.
Imaginons par exemple qu’on code une calculatrice qu’on met à disposition sur notre site pour tous les utilisateurs. Comme vous le savez, il est interdit en mathématiques de diviser un nombre par zéro. On sait donc par avance que ce cas d’utilisation de notre calculatrice va poser problème.
Dans le cas où un utilisateur tente de diviser par zéro, une erreur va donc être provoquée. On va pouvoir prendre en charge ce cas précis en amont en lançant (throw) ce qu’on appelle une exception si celui-ci survient.
Grosso-modo, une exception est une erreur qu’on va déclencher à la place du JavaScript afin de pouvoir plus facilement la gérer. Notez que la plupart des gens emploient les termes « erreur » et « exception » de façon interchangeable et pour désigner la même chose en JavaScript.
Pour définir une exception, nous allons devoir créer un objet à partir de l’un des constructeurs d’erreurs prédéfinis en JavaScript en utilisant la syntaxe new
.
Bien évidemment, on essaiera toujours d’utiliser le constructeur qui fera le plus de sens ou à défaut le constructeur générique Error
avec la syntaxe new Error()
.
On va notamment pouvoir passer un message pour expliquer l’erreur lors de la création de celle-ci plutôt que d’utiliser le message standard proposé par le JavaScript.
Voyons immédiatement comment cela va fonctionner en pratique :
See the Pen
Cours JavaScript 11.1.4 by Pierre (@pierregiraud)
on CodePen.
Pour résumer, ici, on commence par créer une fonction qui divise un nombre par un autre. Les deux nombres vont être envoyés par les utilisateurs via prompt()
.
Pour cette fonction div()
, on peut facilement identifier deux cas d’erreurs qui vont pouvoir se présenter : le cas où les utilisateurs envoient autre chose que des nombres et celui où un utilisateur tente de diviser par zéro.
On va donc prendre en charge ces exceptions en amont, en les isolant dans un bloc if…else if…else
dans la définition de notre fonction et en lançant des objets Erreur
dans chaque cas avec un message personnalisé.
On va ensuite créer nos deux blocs try
et catch
. On tente d’exécuter notre fonction dans le bloc try
et on capture les exceptions dans le bloc catch
. Ce bloc catch
se charge d’afficher le message lié à l’erreur qu’on a défini ci-dessus.
Attention : dès qu’on lance une exception, il faut absolument la capturer dans un bloc catch
à un endroit dans le script.
Le bloc finally
Le bloc finally
est un bloc optionnel qui doit être placé juste après un try…catch
.
Ce bloc nous permet de préciser du code qui sera exécuté dans tous les cas, qu’une erreur ou exception ait été générée ou pas. Notez par ailleurs que les instructions dans un bloc finally
s’exécuteront même dans le cas où une exception est levée mais n’est pas attrapée à la différence du reste du code.
Le bloc finally
va être particulièrement utile dans le cas où on veut absolument effectuer certaines opérations même si une exception est levée comme par exemple récupérer une certaine valeur. Notez par ailleurs que si on utilise finally
pour retourner une valeur, alors la valeur retournée sera considérée comme la valeur de retour pour l’ensemble des blocs try
, catch
et finally
et ceci même si les deux premiers blocs possèdent des instructions return
.
See the Pen
Cours JavaScript 11.1.5 by Pierre (@pierregiraud)
on CodePen.