Les promesses en AngularJS (1/3)

Depuis maintenant quelques années, la vague AngularJS déferle et un grand nombre de projets orientés « Front » l’adoptent presque par défaut désormais. En effet, nous sommes arrivés à un stade où même les clients les moins avertis n’hésitent plus à mentionner AngularJS pour leurs projets, garantis d’être à l’état de l’art (du moins jusqu’à l’arrivée d’AngularJS 2.0 qui va faire table rase de l’existant, mais ceci est une autre histoire).

En conséquence, il y a donc de plus en plus de développeurs qui sont propulsés sur des projets AngularJS et qui peuvent bloquer sur des notions fondamentales du framework : l’injection de dépendances, les directives, le $scope ou encore les promises. Vous l’aurez donc compris, cet article est dédié aux promises en AngularJS. Bien que ces API seront sans doute balayées par l’intégration native des promesses en ECMAScript 6, nombreux seront encore les projets qui s’appuieront sur AngularJS 1.x ; il est donc plus que jamais pertinent d’en comprendre le fonctionnement.

Cette présentation sera en trois articles : dans celui-ci nous verrons tout d’abord qu’est-ce qu’une promesse et comment utiliser les callbacks ; le deuxième se concentrera sur les différents services d’AngularJS qui les utilisent à savoir $http et $resource ; enfin le dernier sera quant à lui consacré à la création de nos propres promesses à l’aide de la librairie Q.

Qu’est-ce qu’une « promesse »

Avant d’aller plus loin, il faut d’abord définir ce qu’est une promesse. Pour cela, je vais m’appuyer sur l’excellente définition de CommonJS qui est d’ailleurs citée par la documentation d’AngularJS : une promesse est un objet représentant le résultat futur d’une action exécutée de manière asynchrone, pouvant donc terminer à n’importe quel moment. Il nous est possible d’y greffer des callbacks de succès et d’erreur, respectivement lorsque la promesse est résolue ou rejetée, afin de pouvoir traiter le résultat renvoyé par la promesse.

Il faut savoir que les promesses sont intensivement utilisées dans AngularJS par le biais de ses services : $http, $resource, $timeout, etc. L’exemple de promesse le plus simple serait justement un GET avec le service $http :

$http.get('/users/1');

Cette action est par nature asynchrone puisqu’elle nécessite de faire une requête HTTP et utilise donc Ajax. Par conséquent, comment faire pour récupérer le résultat du GET sans pour autant attendre la fin de celui-ci et bloquer le traitement ? C’est là que les promesses interviennent :

var promise = $http.get('/users/1');

promise.then(function(value) {
    // successCallback

    console.log(value);
});

Comme on peut le voir ci-dessus, on stocke le résultat de la méthode $http.get() dans une variable que l’on appelle « promise » car c’est effectivement une promesse que le service $http nous renvoie. Cela veut dire que si on voulait récupérer immédiatement la valeur de promise juste après l’avoir initialisé nous n’obtiendrions rien car la promesse n’a pas encore été résolue. Pour cela, nous avons les callbacks. Le callback de succès justement, représenté par la fonction contenue dans then(), prend en argument le résultat renvoyé par la fonction asynchrone – à savoir les données de l’utilisateur dans notre exemple. Il nous est alors possible de logger le détail de notre utilisateur à l’intérieur du callback de succès.

La fonction then() est une des fonctions qu’exposent les objets de type promesse et permet d’appeler des callbacks de succès ou d’erreur selon le résultat de la tâche asynchrone. Avant d’aller plus loin, voici la signature de la méthode then() :

then(successCallback, errorCallback, notifyCallback)

Dans notre exemple précédent je n’ai fourni que le premier argument à la méthode then() car je n’étais pas intéressé par le cas d’erreur. Pour l’instant je ne parlerai pas du troisième argument à savoir le callback de notification ; ce point sera adressé en fin d’article. Cependant voici à quoi ressemble un exemple avec tous les callbacks :

$http.get('/users/1').then(function(value) {
    // successCallback

    }, function(reason) {
    // errorCallback

    }, function(value) {
    // notifyCallback

});

Avant d’aborder les choses vraiment intéressantes telles que les chaînes de promesses et la librairie Q, il faut d’abord faire un petit point sur les services $http et $resource et leurs spécificités. En effet, ces derniers utilisent intensivement les promesses et ils représenteront certainement 90% des promesses que vous manipulerez dans votre application par conséquent ils méritent une partie rien que pour eux. Mais cela sera dans le prochain article de cette présentation !