La
gestion des exceptions en Javascript 1.5
La gestion des exceptions apporte plus de clarté à votre code. Accessible à partir des versions 5 de vos navigateurs préférés (IE, Netscape, Mozilla, Opera), cette technologie s'implémente rapidement.
Java, C++, C#, Cold Fusion, VBScript... sont des langages qui implémentent
une gestion d'exceptions. Si cela ne vous évoque rien, peut-être
l'expression "try... catch..." vous dit-elle quelque
chose ?
Une erreur JavaScript est en fait un type d'exception généré
par l'interpréteur JavaScript. Dans votre carrière
de développeur vous avez sûrement déjà
commis un de ces trésors de la programmation tels qu'une
erreur de syntaxe, une division par zéro ou encore une tentative
d'accès à une partie d'un tableau non définie...
Nous allons ici apprendre à intercepter ces exceptions pour
en extraire des informations compréhensibles, puis nous verrons
comment lancer nos propres exceptions.
Attrapez-les toutes !
L'intérêt d'inclure dans son code une gestion des
exceptions n'est pas seulement de "détourner" les
erreurs les plus voyantes, mais aussi de détecter
celles qui ne se voient pas : ce sont elles qui font perdre au programmeur
le plus de temps lors du déboguage.
Note :
Les balises <SCRIPT> sont placées dans le corps (BODY)
du document HTML afin que les images soient chargées avant
l'exécution du script. Les valeurs renvoyées pour
la largeur sont égales à zéro (ce qui ne remet
pas en question le résultat). Enfin, ce code a été
testé sous IE6.
<BODY>
Image numéro 0 : <IMG SRC="developpeurs.jpg"><br>
Image numéro 1 : <IMG SRC="solutions.gif"><br>
<SCRIPT>
<!--
for(i=0;i<=document.images.length;i++)
{
alert('Largeur
de l\'image numéro '+i+' : '+document.images[i].width+' pixels');
}
document.writeln("Tout s'est
déroulé normalement.")
// -->
</SCRIPT>
</BODY>
Testez
par vous-mêmes ce qui se produit. Nous devrions voir apparaître
à l'écran "Tout s'est déroulé normalement",
or cette phrase n'apparaît pas. Pourquoi ?
En fait le code de cet exemple comporte une erreur classique. Nous
l'évoquions un peu plus haut : l'accès à une
"case" d'un tableau non définie. C'est la boucle
"for" (le "<=" au lieu de "<")
qui pose problème. Elle va s'exécuter 3 fois (entre
i=0 et i=2) alors que la page ne comporte que deux images. Lorsque
nous allons tenter d'afficher la largeur de la troisième
image (la numéro 2), inexistante, une exception sera générée,
interrompant le programme et nous privant de la phrase finale.
Comment aurions-nous pu la détecter ? Grâce à
la mise en place d'une gestion des exceptions :
<BODY>
Image numéro 0 : <IMG SRC="developpeurs.jpg"><br>
Image numéro 1 : <IMG SRC="solutions.gif"><br>
<SCRIPT>
<!--
try
{
for(i=0;i<document.images.length
+ 1;i++)
{
alert('Largeur
de l\'image numéro '+i+' : '+document.images[i].width+' pixels');
}
document.writeln("Tout s'est
déroulé normalement.")
}
catch (error)
{
alert("Une exception JavaScript
a été générée.");
}
// -->
</SCRIPT>
</BODY>
C'est le même code, avec la même erreur. Comparez
son comportement par rapport au premier exemple. La phrase finale
n'est toujours pas affichée (les exceptions ne corrigent
pas les bugs !) mais nous sommes explicitement prévenus par
l'instruction "alert()".
Si notre erreur est détectée, c'est grâce aux
possibilités offertes par le couple "try... catch".
Le principe est simple : Il suffit d'encadrer le code que vous souhaitez
surveiller par un try { }, puis de définir ensuite
dans un catch { } ce que vous voulez faire au cas où
une exception (une erreur) se produit.
Si le code compris dans le try { } s'exécute sans erreur,
alors le catch est ignoré, sinon, l'exécution
du code contenu dans le try { } est stoppée et reprend directement
dans le catch { } correspondant.
Au couple try / catch nous pouvons rajouter l'instruction finally
{ }. Le code qui sera contenu dans ses accolades sera exécuté
quelque soit l'issue du try / catch, exception ou pas. Si le "try"
ne génère pas d'exception, le code contenu dans le
"catch" n'est donc pas exécuté, mais celui
contenu dans "finally" le sera. De même en cas d'exception,
le "try" passe la main au "catch" qui lui-même
passera le relais au code contenu dans les accolades "finally".
Nous sommes alors en droit de nous demander quelle différence
existe-t'il entre le code contenu dans les accolades "finally"
et celui qui est exécuté après un bloc "try
/ catch" (sans instruction "finally") où tout
s'est bien passé.
En fait, lorsque nous plaçons un "try" il est possible
de se passer d'un "catch" ou d'un "finally"
mais pas des deux en même temps. Ainsi, dans le cas ou le
"catch" n'existe pas, un "finally" peut servir
à libérer une ressource suite à une
exception détectée dans un "try", exemple
:
ouvreFichier()
try
{
ecrireFichier(Info)
}
finally
{
fermeFichier() // fermeture de la
ressource
}
Faites parler les exceptions
Selon les navigateurs, il est possible d'obtenir plus ou moins
d'informations sur l'erreur qui vient de se produire. Dans leur
version 5, tous ne supportent pas en effet de la même façon
la gestion des exceptions.
Pas de restrictions pour Netscape
6, Mozilla
ou IE 5.5, par contre IE 5.0 ne supporte pas l'objet "Error"
que nous allons voir maintenant. Quant à Opera
c'est l'instruction "throw", qui sert à
lancer une exception, qui ne passe pas. Pour résumer, le
test qui suit est visible par tous (v5 et +) sauf IE 5.0.
<SCRIPT>
<!--
try
{
document.writeln("Pour l'instant
tout se passe bien...<br>")
eval("15+*3")
document.writeln("Fin du bloc,
tout s'est bien passé ?<br>")
}
catch(err)
{
document.writeln("Une exception
a eu lieu !<br>")
document.writeln("Nom de l'exception
: " + err.name+"<br>")
document.writeln("Message d'erreur
reçu : " + err.message)
}
// -->
</SCRIPT>
Nous avons volontairement introduit une erreur de syntaxe, JavaScript
ne pourra pas venir à bout de ce calcul, observez-le
générer une exception. La variable "err"
véhicule l'objet Error issu de l'exception générée,
nous pouvons alors l'exploiter grâce aux propriétés
"name" et "message".
En plus de "SyntaxError", il existe cinq autres types
d'erreur disponibles directement :
EvalError, RangeError, ReferenceError, TypeError et URIError.
Lancez vos propres exceptions
Nous évoquions tout à l'heure l'instruction "throw"
(non supportée par Opera 5.0), capable de lancer une exception,
elle peut vous permettre de créer vos propres erreurs personnalisées.
Un exemple :
<SCRIPT>
<!--
var chaine
try
{
chaine = "A";
throw new Error("*exception*");
chaine = chaine+"B";
}
catch(error)
{
chaine = chaine+error.message;
}
chaine = chaine+"C";
alert(chaine)
// -->
</SCRIPT>
Cet exemple met en évidence le chemin parcouru lorsqu'une
exception est rencontrée. Aucune erreur de code n'est à
signaler, nous avons simplement "forcé" le lancement
d'une exception. Sans elle nous aurions obtenu la chaine "ABC",
voyez
ce qu'il en est réellement.
Nous ne pouvons pas aborder ici toutes les propriétés
des blocs "try / catch", sachez néanmoins qu'ils
peuvent s'imbriquer entre eux.
Les grands principes de la gestion des exceptions en JavaScript
ont été évoqués. Si vous souhaitez aller
plus loin et vous construire par exemple une gestion des exceptions
plus personnalisé, un
peu documentation vous sera utile.
Par ailleurs, de futurs articles examineront les exceptions pour
d'autres langages, notamment le PHP.
[Arnaud
Gadal 31
octobre 2001 , JDNet]
|