Apprendre Javascript pour rendre vos pages Web interactives

Auteur: Mohamed CHINY Durée necessaire pour le cours de Apprendre Javascript pour rendre vos pages Web interactives Niveau recommandé pour le cours de Apprendre Javascript pour rendre vos pages Web interactives Supports vidéo disponibles pour ce cours Exercices de renforcement disponibles pour ce cours Quiz disponible pour ce cours

Page 34: Gérer les promesses avec une fonction asynchrone - async et await

Toutes les pages

Fonctions asynchrones (async et await)

Gérer une promesse à l'aide d'une fonction asynchrone

Nous avons vu qu’une promesse permet de différer un traitement. En effet, elle ne délivre pas une valeur au moment même, mais seulement une promesse de cette valeur-là, et quand cette ci sera disponible, alors elle sera transmise au script pour poursuivre son exécution sans bloquer le traitement qui ne dépend pas de la promesse. Pour gérer une promesse, on utilise les méthodes then et catch. Cependant, dans le cas du chaînage de promesses on se retrouve avec un code un peu différent de la structure dont on a l’habitude de voir dans un programme informatique. C’est pour cette raison qu’il existe une autre méthode qui permet de gérer les promesses à l’aide des mots-clés async et await et ce qui a pour effet de créer un code plus convivial.

La structure d'une promesse gérée à l'aide d'une fonction asynchrone se rapproche de la forme habituelle d'un programme, c'est à dire, une forme imbriquée qui présente des blocs de traitements qui dépendent d'autres blocs (comme les conditions, les boucles ou les blocs try...catch).

Prenons le code de la dernière fois et qui consiste à générer un nombre pair compris entre 0 et 10:
new Promise((resolve,reject)=>{
   nbr=Math.round(Math.random()*10);
   if(nbr%2==0)
      setTimeout(()=>resolve("Nombre pair"),500);
   else
      setTimeout(()=>reject("Nombre impair"),500);
}).then((val)=>{
   console.log(val);
}).catch((val)=>{
   console.log(val);
})
On considère que la promesse renvoie fulfilled si le nombre et pair et rejected si le nombre est impair.
Dans ce code, j'ai pris le soin d'ajouter un temporisateur qui dure 500ms avant de renvoyer un résultat. Cela permet de mieux comprendre l'importance des promesses vis-à-vis du traitement des tâches qui requièrent du temps.
Maintenant, nous allons faire le même traitement du code précédent, mais à l'aide d'une fonction asynchrone.

Premièrement, on va créer une fonction nommée getNbrPair() qui retourne le nombre généré. Ce nombre sera toujours généré à l'aide d'une promesse, mais au lieux de programmer les deux fonctions de callback resolve() et reject(), nous n'allons conserver que la fonction resolve(). En effet, nous allons recourir à la gestion des exceptions à l'aide des mots-clés try, throw et catch. Autrement dit, le traitement du block catch de la promesse sera remplacé par le traitement du bloc catch de la gestion des exceptions.

Notre fonction ressemblera à ceci:
function genNbrPair(){
   return new Promise(resolve=>{
      try{
         nbr=Math.round(Math.random()*10);
         if(nbr%2==0)
            setTimeout(()=>resolve("Nombre pair"),500);
         else
            throw new Error("Nombre impair");
      }
      catch(err){
         setTimeout(()=>console.log(err.message),500);
      }
   })
}
Notez que le setTimeout() du bloc catch est seulement là pour que le comportement au moment de l'exécution soit identique à celui du code initial. Sinon on pourrait le retirer et afficher directement le message à la console.

Maintenant, il est temps de créer notre fonction asynchrone qui accueillera le nombre retourné par la fonction que l'on vient de créer.

Une fonction asynchrone est précédée par le mot-clé async afin d'informer le moteur Javascript qu'elle est sensé renfermer un traitement différé dans le temps. Quant à ce traitement-là (le traitement qui risque de prendre un moment pour s'accomplir), il doit être précédé par le mot-clé await. Bien entendu, il s'agira là de l'appel de la fonction genNbrPair().

Notre code complet ressemblera à ceci:
// Déclaration de la fonction qui referme la promesse
function genNbrPair(){
   return new Promise(resolve=>{
      try{
         nbr=Math.round(Math.random()*10);
         if(nbr%2==0)
            setTimeout(()=>resolve("Nombre pair"),500);
         else
            throw new Error("Nombre impair");
      }
      catch(err){
         setTimeout(()=>console.log(err.message),500);
      }
   })
}

// Déclaration de la fonction asynchrone
async function appel(){
   nbr=await genNbrPair();
   console.log(nbr);
}

// Appel de la fonction asynchrone
appel();
Le mot-clé await informe le moteur Javascript qu'il doit attendre la fin du traitement qui sera assuré par la fonction genNbrPair(). Cela veut dire que l'exécution est bloquée à ce point et aucune autre instruction dans la fonction courante ne peut être exécutée avant la fin du traitement en question. Par contre, tous les traitements qui ne dépendent pas de la promesse poursuivront leur exécution normalement.
Il faut notre que l'invocation du mot-clé await doit impérativement être faite au sein d'une fonction asynchrone (préfixée par async).

Fonctions asynchrones et promesses (async & await) en vidéo