Promise.all vs. promise.race en JavaScript

Une promise peut dépendre de l'achèvement d'une liste d'opérations et non du résultat d'une seule opération.

On a vu dans la première partie, Promise, qu'il est possible de différer un traitement, de l'associer à la réalisation à venir d'une condition. Et quand le résultat attendu arrive, selon qu'il est positif ou négatif, le traitement qui en dépend sera effectué ou non.

Il est aussi possible d'attendre non pas la fin d'un traitement, mais la fin d'une liste de traitements. L'objet Promise dispose de deux méthodes différentes pour le traiter, all et race, et nous allons voir comment elles fonctionnent dans deux exemples.

Compatibilité: Edge, Firefox, Chrome, Safari, Opera.

TEST DE COMPATIBILITE

Pour information, le code du test de compatibilité est le suivant:

Promise.all([true]).then(function(result) {
  document.getElementById("test").innerHTML = "Supporté!";
});

Affiche "Supporté!" si la méthode all de Promise est reconnue, sinon rien n'est affiché.
En effet, le paramètre de la méthode all est un tableau d'un seul élément, true (la valeur "vrai"), donc le résultat du test est toujours un succès, mais il n'y a de résultat que si l'objet est implémenté dans le navigateur.

Promise.all

Promise.all abouti a un succès quand toutes les conditions sont remplies, ou abouti à un échec dès qu'une seule des conditions échoue (sans attendre le résultat des autres).

On recourt à cette méthode quand on attend le résultat de plusieurs traitement asynchrones et que le traitement à suivre requiert que tous aboutissent à un succès.

La syntaxe de la méthode est la suivante:

Promise.all(  ... tableau de promises... ).then(fonction success, fonction fail)

Le paramètre de all est un tableau d'objets de type promise. On peut y mettre aussi des valeurs, elle sont converties en interne en appels de promise.resolve. La méthode then à pour paramètres deux fonctions, la première est exécutée en cas de succès (tous les éléments du tableau sont des succès) et la seconde en cas d'échec (un élément du tableau au moins est un échec).

Pour illustrer cela, on vous demande de cocher trois cases, et les mettre sur ON ou OFF. On considère ON comme un succès et OFF comme un échec. La méthode promise.all se base sur ce qui est coché pour afficher "succès" ou "échec". Cette démonstration à un seul but d'exposition et pas forcément d'intérêt pratique.

Cochez les trois cases:

Démonstration
Option 1 :     ON OFF
Option 2 :     ON OFF
Option 3 :     ON OFF

Résultat

Code HTML:

<form name="pall">
<table>
<tr><td>Option 1 :
ON <input type="radio" name="r1" value="ON">
OFF <input type="radio" name="r1" value="OFF" checked>
</td></tr>
<tr><td>Option 2 :
ON <input type="radio" name="r2" value="ON" checked>
OFF <input type="radio" name="r2" value="OFF">
</td></tr>
<tr><td>Option 3 :
ON <input type="radio" name="r3" value="ON">
OFF <input type="radio" name="r3" value="OFF" checked>
</td></tr>
</table> <input type="button" value="PROMISE" onclick="start()">

Code JavaScript:

function checkRow(id) {
  var y = document.pall[id];
  return ((y[0].checked) ? true : false);
}

function p1(success, fail) {
  if(checkRow("r1")) success(); else fail();
}

function p2(success, fail) {
  if(checkRow("r2")) success(); else fail();
}

function p3(success, fail) {
  if(checkRow("r3")) success(); else fail();
}

function overallSuccess() { document.getElementById("result").innerHTML = "Succès!" }

function overallFail()    { document.getElementById("result").innerHTML = "Echec."  }

function start() {
  var pa1 = new Promise(p1)
  var pa2 = new Promise(p2)
  var pa3 = new Promise(p3)
  Promise.all([pa1, pa2, pa3]).then(overallSuccess, overallFail)
}	

Promise.race

Promise.race, place le programme en attente du résultat de la première condition testée dans une liste. Selon que le résultat est un succès ou un échec, promise.race est un succès ou un échec, sans attendre le résultat des autres conditions.

On recourt à cette instruction quand un traitement à suivre dépend d'un autre traitement parmi plusieurs que l'on a déclenchés et que le résultat d'un seul soit suffisant pour poursuivre. On n'a donc pas besoin que tous les traitements retournent un résultat.

Pour y trouver une application pratique, on doit imaginer que tous les traitements déclenchés dépendent d'une même entité et que celle-ci détermine leurs résultats.

La syntaxe est la suivante:

Promise.race(  ... tableau de promises... ).then(fonction success, fonction fail)

Exemple pratique

Une application coté client veut charger une image sur le serveur. Elle lance deux opérations, la première tente de charger le fichier par WebSocket, la seconde de le charger grâce à Ajax.
Si l'une des deux opérations ne trouve pas le fichier, c'est un échec et cela est transmis à promise.race. Dès que l'une des deux trouve le fichier, c'est un succès et promise.race poursuit le traitement, par exemple afficher l'image.

Code:

function loadAjax(nomfichier) {
   ... code ajax ...
}

function loadWebSocket(nomfichier) {
   ... code websocket ...
}

var p1 = new Promise(function(success, fail) {
   if(loadAjax("nom.png")) success()
   else fail()
})

var p2 = new Promise(function(success, fail) {
   if(loadWebSocket("nom.png")) success()
   else fail()
})

function dispImage() {
   ... afficher image...
}

function dispErreur() {
   ... afficher "non trouvé"...
}

Promise.race( [p1, p2] ).then( dispImage, dispErreur )

Voir aussi:

© 1 février 2016 Xul.fr