Les promesses en AngularJS (3/3)
Troisième et dernier article de cette présentation, nous allons à présent rentrer dans le cœur du sujet et certainement ce qui vous intéresse le plus : au final, comment fonctionne une promesse en interne ? Comment fait-on pour créer soi-même une promesse ? Pour enchaîner / combiner des promesses entre elle ? Tout cela sera couvert dans ce dernier article.
Créer une promesse maison avec $q
Jusqu’à présent, nous avons vu le fonctionnement des promesses et leur utilisation dans les services fournis par AngularJS. Nous allons à présent voir comment créer nos propres promesses. Pour cela, AngularJS s’appuie sur $q qui est une implémentation de la librarie Q en Javascript. Voici un exemple :
Plusieurs choses se passent ici. Dans un premier temps, on crée un objet « deferred ». Ce type d’objet contient 4 éléments : 3 fonctions et un autre objet. Les trois fonctions sont les suivantes : `resolve(value)`, `reject(reason)` et `notify(value)`. Le quatrième élément est un objet de type « promise » qui va justement nous permettre de renvoyer la promesse.Une fois l’objet deferred créé, on peut alors soit résoudre la promesse par l’appel de la fonction resolve(value)
, soit la rejeter avec reject(reason)
. Nous ne parlerons toujours pas de notify(value)
pour l’instant. On retourne ensuite la promesse via deferred.promise
afin que notre fonction soit « thenable » c’est à dire que l’on puisse enchaîner l’appel de notre fonction par then()
et y greffer des callbacks de succès et d’erreur. De manière générale, le fait de retourner la promesse vous donne accès à toutes les fonctions de l’API des promesses : then(successCallback, errorCallback, notifyCallback)
que nous connaissons bien maintenant mais aussi catch(errorCallback)
qui est un raccourci pour then(null, errorCallback)
, ou encore finally(callback, notifyCallback)
qui est toujours appelé, que la promesse soit résolue ou rejetée.
Créer une chaîne de promesses
En prenant comme exemple la fonction getPromise()
définie ci-dessus, on pourrait donc imaginer ce genre de choses :
Si vous souhaitez tester tout cela vous-même, je vous invite à consulter l’exemple ci-joint dans lequel la fonction getPromise()
est définie et accompagnée d’un exemple fonctionnel.
Combiner plusieurs promises en une seule
Quelque chose que l’on n’a pas encore évoqué jusqu’à présent : comment faire pour traiter un ensemble de promesses comme un seul et même traitement et réagir en fonction du résultat de cet ensemble et non indépendamment sur chaque promesse ? Pour cela c’est très simple, il y a $q.all([promises])
. Voici un exemple :
Vous trouverez un exemple d’utilisation à cette adresse. Cet article approche à sa fin, mais il nous reste encore quelques fonctions bien utiles à couvrir…
Quelques méthodes utiles : when(), notify()
La méthode when(value)
permet de « wrapper » la valeur fournie dans une promesse afin de bénéficier de l’API et de pouvoir enchaîner sur d’autres promesses à l’aide de then()
par exemple. Cela peut s’avérer utile lorsque le point d’entrée de la chaîne de promesses n’est justement pas une promesse : une fonction d’une librairie tierce ou tout simplement une valeur.
Pour un exemple plus avancé de notify()
(appels récursifs, notifications avec des barres de progression Bootstrap, etc.) je vous invite vivement à jeter un œil à cet exemple sur Plunker.
Je pense que nous avons fait le tour des fonctionnalités des promesses en AngularJS 1.3. Si vous souhaitez revenir sur l’intégralité des exemples couverts par cet article vous pouvez consulter mon JSFiddle. Enfin, n’hésitez surtout pas à me donner votre feedback dans les commentaires.