ES6 - Promesses

Syntaxe de promesse

La syntaxe liée à la promesse est mentionnée ci-dessous où, p est l'objet de la promesse, resolve est la fonction qui doit être appelée lorsque la promesse s'exécute avec succès et reject est la fonction qui doit être appelée lorsque la promesse rencontre une erreur.

let p = new Promise(function(resolve,reject){
   let workDone = true; // some time consuming work
      if(workDone){
      //invoke resolve function passed
      
	  resolve('success promise completed')
   }
   else{
      reject('ERROR , work could not be completed')
   }
})

Exemple

L'exemple ci-dessous montre une fonction add_positivenos_async()qui ajoute deux nombres de manière asynchrone. La promesse est résolue si des valeurs positives sont passées. La promesse est rejetée si des valeurs négatives sont passées.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed') 
         })
         return p;
   }

   add_positivenos_async(10, 20)
      .then(successHandler) // if promise resolved
      .catch(errorHandler);// if promise rejected

   add_positivenos_async(-10, -20)
      .then(successHandler) // if promise resolved
      .catch(errorHandler);// if promise rejected

   function errorHandler(err) {
      console.log('Handling error', err)
   }
   function successHandler(result) {
      console.log('Handling success', result)
   }

   console.log('end')
</script>

La sortie du code ci-dessus sera comme mentionné ci-dessous -

end
Handling success 30
Handling error NOT_Postive_Number_Passed

Enchaînement des promesses

Promises chaining peut être utilisé lorsque nous avons une séquence de asynchronous tasksà faire les uns après les autres. Les promesses sont enchaînées lorsqu'une promesse dépend du résultat d'une autre promesse. Ceci est illustré dans l'exemple ci-dessous

Exemple

Dans l'exemple ci-dessous, add_positivenos_async() functionajoute deux nombres de manière asynchrone et rejette si des valeurs négatives sont passées. Le résultat de l'appel de fonction asynchrone en cours est passé en paramètre aux appels de fonction suivants. Notez chaquethen() a une instruction return.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })
      return p;
   }

   add_positivenos_async(10,20)
   .then(function(result){
      console.log("first result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
   console.log("second result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
      console.log("third result",result)
   })

   console.log('end')
</script>

La sortie du code ci-dessus sera comme indiqué ci-dessous -

end
first result 30
second result 60
third result 120

Certaines méthodes couramment utilisées de l'objet de promesse sont décrites ci-dessous en détail -

promise.all ()

Cette méthode peut être utile pour agréger les résultats de plusieurs promesses.

Syntaxe

La syntaxe du promise.all() méthode est mentionnée ci-dessous, où, iterableest un objet itérable. Par exemple, Array.

Promise.all(iterable);

Exemple

L'exemple donné ci-dessous exécute un tableau d'opérations asynchrones [add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]. Lorsque toutes les opérations sont terminées, la promesse est entièrement résolue.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }
   //Promise.all(iterable)

Promise.all([add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)])
   .then(function(resolveValue){
      console.log(resolveValue[0])
      console.log(resolveValue[1])
      console.log(resolveValue[2])
      console.log('all add operations done')
   })
   .catch(function(err){
      console.log('Error',err)
   })
   console.log('end')
</script>

La sortie du code ci-dessus sera la suivante -

end
30
70
110
all add operations done

promise.race ()

Cette fonction prend un tableau de promesses et retourne la première promesse réglée.

Syntaxe

La syntaxe du promise.race()function est mentionnée ci-dessous, où, iterable est un objet itérable. Par exemple, Array.

Promise.race(iterable)

Exemple

L'exemple donné ci-dessous prend un tableau [add_positivenos_async(10,20),add_positivenos_async(30,40)] des opérations asynchrones.

La promesse est résolue chaque fois que l'une des opérations d'ajout se termine. La promesse n'attendra pas la fin des autres opérations asynchrones.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         } else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }

   //Promise.race(iterable)
   Promise.race([add_positivenos_async(10,20),add_positivenos_async(30,40)])
   .then(function(resolveValue){
      console.log('one of them is done')
      console.log(resolveValue)
   }).catch(function(err){
      console.log("Error",err)
   })

   console.log('end')
</script>

La sortie du code ci-dessus sera la suivante -

end
one of them is done
30

Promisessont un moyen simple d'implémenter la programmation asynchrone en JavaScript (nouvelle fonctionnalité ES6). Avant les promesses, les rappels étaient utilisés pour implémenter la programmation asynchrone. Commençons par comprendre ce qu'est la programmation asynchrone et son implémentation, à l'aide des rappels.

Comprendre le rappel

Une fonction peut être passée en paramètre à une autre fonction. Ce mécanisme est appeléCallback. Un rappel serait utile dans les événements.

L'exemple suivant nous aidera à mieux comprendre ce concept.

<script>   
   function notifyAll(fnSms, fnEmail) {   
      console.log('starting notification process');   
      fnSms();   
      fnEmail();   
   }   
   notifyAll(function() {   
      console.log("Sms send ..");   
   }, 
   function() {   
      console.log("email send ..");   
   });   
   console.log("End of script"); 
   //executes last or blocked by other methods   
</script>

dans le notifyAll()méthode ci-dessus, la notification se fait par l'envoi de SMS et par l'envoi d'un e-mail. Par conséquent, l'appelant de la méthode notifyAll doit passer deux fonctions en tant que paramètres. Chaque fonction assume une seule responsabilité comme l'envoi de SMS et l'envoi d'un e-mail.

La sortie suivante s'affiche lors de l'exécution réussie du code ci-dessus.

starting notification process 
Sms send .. 
Email send .. 
End of script

Dans le code mentionné ci-dessus, les appels de fonction sont synchrones. Cela signifie que le thread de l'interface utilisateur attendrait pour terminer tout le processus de notification. Les appels synchrones deviennent des appels bloquants. Comprenons maintenant les appels non bloquants ou asynchrones.

Comprendre AsyncCallback

Prenons l'exemple ci-dessus.

Pour activer le script, exécutez un appel asynchrone ou non bloquant à la méthode notifyAll (). Nous utiliserons lesetTimeout()méthode de JavaScript. Cette méthode est asynchrone par défaut.

La méthode setTimeout () prend deux paramètres -

  • Une fonction de rappel.

  • Le nombre de secondes après lequel la méthode sera appelée.

Dans ce cas, le processus de notification a été encapsulé avec timeout. Par conséquent, cela prendra un délai de deux secondes, défini par le code. La fonction notifyAll () sera invoquée et le thread principal continuera comme exécutant d'autres méthodes. Par conséquent, le processus de notification ne bloquera pas le thread JavaScript principal.

<script>   
   function notifyAll(fnSms, fnEmail) {   
      setTimeout(function() {   
         console.log('starting notification process');   
         fnSms();   
         fnEmail();   
      }, 2000);   
   }   
   notifyAll(function() {   
      console.log("Sms send ..");   
   },  
   function() {   
      console.log("email send ..");   
   });   
   console.log("End of script"); //executes first or not blocked by others   
</script>

La sortie suivante s'affiche lors de l'exécution réussie du code ci-dessus.

End of script 
starting notification process 
Sms send .. 
Email send ..

En cas de rappels multiples, le code aura l'air effrayant.

<script>   
   setTimeout(function() {   
      console.log("one");   
      setTimeout(function() {   
         console.log("two");   
         setTimeout(function() {   
            console.log("three");   
         }, 1000);   
      }, 1000);   
   }, 1000);   
</script>

ES6 vient à votre secours en introduisant le concept de promesses. Les promesses sont des "événements de continuation" et elles vous aident à exécuter les multiples opérations asynchrones ensemble dans un style de code beaucoup plus propre.

Exemple

Comprenons cela avec un exemple. Voici la syntaxe pour le même.

var promise = new Promise(function(resolve , reject) {    
   // do a thing, possibly async , then..  
   if(/*everthing turned out fine */)    resolve("stuff worked");  
   else     
   reject(Error("It broke"));  
});  
return promise;
// Give this to someone

La première étape vers la mise en œuvre des promesses est de créer une méthode qui utilisera la promesse. Disons que dans cet exemple, legetSum()est asynchrone, c'est-à-dire que son fonctionnement ne doit pas bloquer l'exécution des autres méthodes. Dès que cette opération est terminée, il en informera ultérieurement l'appelant.

L'exemple suivant (étape 1) déclare un objet Promise «var promise». Le Promise Constructor prend d'abord les fonctions pour la réussite du travail et une autre en cas d'erreur.

La promesse renvoie le résultat du calcul en utilisant le callback de résolution et en passant le résultat, c'est-à-dire n1 + n2

Step 1 - résoudre (n1 + n2);

Si getSum () rencontre une erreur ou une condition inattendue, il appellera la méthode de rappel de rejet dans la promesse et transmettra les informations d'erreur à l'appelant.

Step 2 - rejeter (Erreur ("Négatifs non pris en charge"));

L'implémentation de la méthode est donnée dans le code suivant (ÉTAPE 1).

function getSum(n1, n2) {   
   varisAnyNegative = function() {   
      return n1 < 0 || n2 < 0;   
   }   
   var promise = new Promise(function(resolve, reject) {   
      if (isAnyNegative()) {   
         reject(Error("Negatives not supported"));   
      }   
      resolve(n1 + n2)
   });   
   return promise;   
}

La deuxième étape détaille la mise en œuvre de l'appelant (ÉTAPE 2).

L'appelant doit utiliser la méthode «alors», qui prend deux méthodes de rappel - la première pour le succès et la seconde pour l'échec. Chaque méthode prend un paramètre, comme indiqué dans le code suivant.

getSum(5, 6)   
.then(function (result) {   
   console.log(result);   
},   
function (error) {   
   console.log(error);   
});

La sortie suivante s'affiche lors de l'exécution réussie du code ci-dessus.

11

Puisque le type de retour de getSum () est une promesse, nous pouvons en fait avoir plusieurs instructions «then». Le premier «alors» aura une instruction de retour.

getSum(5, 6)   
.then(function(result) {   
   console.log(result);   
   returngetSum(10, 20); 
   // this returns another promise   
},   
function(error) {   
   console.log(error);   
})   
.then(function(result) {   
   console.log(result);   
}, 
function(error) {   
   console.log(error);
});

La sortie suivante s'affiche lors de l'exécution réussie du code ci-dessus.

11
30

L'exemple suivant émet trois appels then () avec la méthode getSum ().

<script>   
   function getSum(n1, n2) {   
      varisAnyNegative = function() {   
         return n1 < 0 || n2 < 0;   
      }   
      var promise = new Promise(function(resolve, reject) {   
         if (isAnyNegative()) {   
            reject(Error("Negatives not supported"));   
         }   
         resolve(n1 + n2);   
      });   
      return promise;   
   }   
   getSum(5, 6)   
   .then(function(result) {   
      console.log(result);   
      returngetSum(10, 20); 
      //this returns another Promise   
   },   
   function(error) {   
      console.log(error);   
   })
   .then(function(result) {   
      console.log(result);   
      returngetSum(30, 40); 
      //this returns another Promise   
   }, 
   function(error) {   
      console.log(error);   
   })   
   .then(function(result) {   
      console.log(result);   
   }, 
   function(error) {         
      console.log(error);   
   });   
   console.log("End of script ");   
</script>

La sortie suivante s'affiche lors de l'exécution réussie du code ci-dessus.

Le programme affiche d'abord «fin de script», puis les résultats de l'appel de la méthode getSum (), un par un.

End of script  
11 
30 
70

Cela montre que getSum () est appelé dans un style asynchrone ou non bloquant. Promise offre un moyen agréable et propre de gérer les rappels.