Promise en Javascript : comprendre les promesses
Techniquement parlant une promesse n’est rien d’autre que l’objet Promise :
let unePromesse = new Promise();
Mais à quoi va servir cet objet? Et bien à synchroniser deux actions (ou plus) qui se déroulent dans le temps mais pas à la même vitesse.
Pour faire un parallèle avec la vie courante, imaginez que vous êtes autour d’une table avec des amis et que vous voulez trinquer (fonction jeTrinque()), vous êtes conscient qu’il faut d’abord attendre que le serveur vous apporte un verre de champagne (function commandeVerre()). Même si vous ne savez pas exactement dans combien de temps il viendra, vous êtes persuadé que votre verre finira par arriver, et qu’au pire vous serez prévenu en cas de rupture de stock. C’est comme si, quelque part, il vous en avait fait la promesse.
On va maintenant illustrer cet exemple avec le code Javascript. La fonction commandeVerre() sera encapsuler dans la promesse :
let unePromesse = new Promise( function(resolve, reject) { // fonction commandeVerre // au bout de 3 secondes le serveur apporte du champagne setTimeout(function() { resolve('champagne'); }, 3000); } );
Vous remarquez qu’au bout de trois seconde la fonction exécute resolve() qui est la fonction passée en argument et qui correspondra à votre fonction jeTrinque(). A ce stage, il ne se passe rien : on effectue seulement une mise en mémoire des actions à enchaîner par la promesse. Vous remarquez aussi la présence d’un autre argument reject et qui correspondra à la fonction à exécuter en cas d’échec.
Pour exécuter une promesse il suffit d’appliquer la méthode then() sur l’objet Promise :
function jeTrinque(boisson){ alert("Je trinque avec du " + boisson); } unePromesse.then(jeTrinque); // affichera 'Je trinque avec du champagne'
Vous passez, en argument de la méthode, votre fonction jeTrinque() qui se retrouvera dans la fonction resolve de la promesse. Vous remarquez que votre fonction jeTrinque() récupère l’argument ‘champagne’ à travers le paramètre boisson.
Testez en ligne le résultat.
Créer une fonction asynchrone
Dans notre exemple ci-dessus, le serveur du bar nous retourne du champagne. Mais si je souhaite choisir ma boisson, comment la transmettre dans la promesse. Vous ne pouvez pas directement la fournir dans l’objet Promise. La technique consiste donc à passer par un fonction dîtes asynchrone.
Le principe consiste à transmettre la boisson à travers l’argument de la fonction asynchrone qui la retransmet (par closure) à la promesse :
function commandeVerre(maBoisson){ // fonction asynchrone return new Promise( // la fonction retourne la promesse function(resolve, reject) { // au bout de 3 secondes le serveur apporte du champagne setTimeout(function() { resolve(maBoisson); }, 3000); } ); } function jeTrinque(boisson){ alert("Je trinque avec du " + boisson); } let unePromesse = commandeVerre("vin rouge"); unePromesse.then(jeTrinque);
Grâce à cette technique nous pouvons choisir notre boisson!
La fonction asynchrone retourne la promesse, récupérer par la variable unePromesse et nous l’exécutons comme tout à l’heure avec la méthode then().
Testez en ligne le résultat.
Enchaîner les promesses
Il est possible d’enchaîner plusieurs actions. Chaque action peut même transmettre à la suivante une valeur.
Restons avec notre exemple ci-dessus et ajoutons après l’action jeTrinque(), l’action jeBois().
function commandeVerre(maBoisson){ // fonction asynchrone return new Promise( // la fonction retourne la promesse function(resolve, reject) { // au bout de 3 secondes le serveur apporte du champagne setTimeout(function() { resolve(maBoisson); }, 3000); } ); } function jeTrinque(boisson){ alert("Je trinque avec du " + boisson); return boisson; } function jeBois(boisson){ alert("je bois le " + boisson); } let unePromesse = commandeVerre("vin rouge"); unePromesse.then(jeTrinque).then(jeBois);
Il suffit de rajouter à nouveau la méthode then() sur la même promesse pour enchaîner les deux actions.
Vous remarquez que la fonction jeTrinque() transmet la valeur boisson à la fonction jeBois().
Testez en ligne le résultat.