0% ont trouvé ce document utile (0 vote)
2 vues24 pages

6-Promises Et Requêtage HTTP

Ce document traite des Single Page Applications (SPA) et de la gestion des requêtes asynchrones en JavaScript, en mettant l'accent sur l'utilisation des promises pour simplifier la gestion des callbacks. Il explique comment AngularJS utilise le service $q pour créer et manipuler des promises, ainsi que le service $http pour effectuer des requêtes HTTP. Les concepts de résolution, rejet et notification des promises sont également abordés, ainsi que les méthodes associées pour gérer les résultats des actions asynchrones.

Transféré par

ducman.nguyen85
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
2 vues24 pages

6-Promises Et Requêtage HTTP

Ce document traite des Single Page Applications (SPA) et de la gestion des requêtes asynchrones en JavaScript, en mettant l'accent sur l'utilisation des promises pour simplifier la gestion des callbacks. Il explique comment AngularJS utilise le service $q pour créer et manipuler des promises, ainsi que le service $http pour effectuer des requêtes HTTP. Les concepts de résolution, rejet et notification des promises sont également abordés, ainsi que les méthodes associées pour gérer les résultats des actions asynchrones.

Transféré par

ducman.nguyen85
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Introduction

Dans un site web classique, le rôle du serveur est de fournir des pages que le navigateur affichera. Dans une SPA,
son rôle est différent. Puisque toute la gestion de la navigation, de l’affichage des données et des pages est gérée
côté client, en JavaScript, le serveur se libère de ces responsabilités et devient une API Web. Son rôle est de renvoyer
des données, généralement au format JSON.

Les notions de promises, permettant de chaîner des actions asynchrones, et les mécanismes de requêtage HTTP
fournis par AngularJS seront évoqués dans ce chapitre.

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 1-


Promise, la fin des callbacks
JavaScript est un langage mono­threadé par design et se base sur un modèle événementiel non bloquant. Cela
implique que ce langage utilise beaucoup le mécanisme d’actions asynchrones et s’appuie sur le principe de callback
pour gérer cet asynchronisme.

Une fonction non asynchrone renvoie une valeur ou un objet.

var result = addition(4, 8)

La méthode addition est synchrone et renvoie le résultat de l’addition entre ses deux paramètres. La variable result a
alors pour valeur 12.

Une fonction JavaScript asynchrone ne renvoie pas de résultat mais va prendre en paramètre une fonction de callback
qui sera appelée lorsque le traitement sera terminé. Cette fonction de callback va elle­même prendre en paramètre
les résultats du traitement.

step1(function(value1) {
// Traitement lorsque l’exécution de la fonction est terminée
});

La méthode step1 est asynchrone et prend en paramètre une fonction callback. Cette fonction est appelée lorsque l’exécution
de l’action asynchrone est terminée, et prend en paramètre la valeur résultante de l’action.

Bien que ce mécanisme fonctionne, il devient difficile à utiliser lorsqu’il est nécessaire de manipuler plusieurs fonctions
asynchrones, par exemple pour effectuer des appels chaînés ou parallèles, ou bien lorsqu’il est souhaitable de mettre
en place une gestion des erreurs globales à plusieurs appels de fonctions asynchrones.

step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Traitement lorsque l’exécution des quatre
// fonctions asynchrones est terminée
});
});
});
});

Le code précédent chaîne l’exécution de plusieurs méthodes asynchrones. La méthode step2 est appelée dans le callback de la
méthode step1, la méthode step3 dans le callback de la méthode step2 et la méthodestep4 dans le callback de la
méthode step3.

L’imbrication de callbacks, comme vu dans l’exemple précédent, est une syntaxe qui est appelée Pyramid of Doom et
qui est une syntaxe rencontrée fréquemment lorsqu’une application JavaScript utilise beaucoup d’asynchronisme. Le
problème de cette syntaxe vient de sa structuration qui rend la lisibilité difficile, et donc la maintenabilité moins facile.

Pour avoir un fonctionnement plus souple, plus simple à mettre en place et plus lisible, la notion de promise a été
créée.

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 1-


1. Promise

Une promise, ou promesse en français, représente l’attente d’un résultat d’une action asynchrone. Cette notion
permet de se passer des callbacks, les fonctions asynchrones n’en prenant plus en paramètre mais renvoyant une
promise.

var todoId = 5;
var promise = recupererTodo(todoId);

La fonction recupererTodo ne prend pas de callback en paramètre mais renvoie une promise, représentant l’attente du
résultat de la fonction.

Une promise peut avoir trois états. Lorsque l’action asynchrone est en cours, la promise sera dans un état d’attente
de résultat. Une fois que l’action asynchrone est terminée, la promise sera soit dans un état de succès, soit dans un
état d’échec. Une fois en succès ou en échec, la promise ne pourra plus changer d’état.

Un objet promise est caractérisé par une méthode then permettant d’agir en cas de modification de son état.

var promise = step1()


.then(function(value1) {
// Promise résolue avec succès
}, function(error) {
// Promise résolue avec erreur
});

La méthode then de la promise renvoie une nouvelle promise. Cela permet de pouvoir chaîner des actions
asynchrones.

var promise = step1()


.then(function(value1) {
return step2(value1);
})
.then(function(value2) {
return step3(value2);
})
.then(function(value3) {
return step4(value3);
})
.then(function (value4) {
// Traitement lorsque l’exécution des quatre fonctions
// asynchrones est terminée
});

Le mécanisme de promise n’est pas natif dans JavaScript et n’est pas non plus lié à AngularJS. La plupart des
frameworks JavaScript implémentent leur propre système de promise, comme jQuery ou WinJS.

AngularJS implémente lui aussi son propre système de promise, intégré à son architecture.

Tout le mécanisme des promises d’AngularJS est encapsulé dans le service $q.

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


2. Création d’une promise

Le service $q fournit une méthode defer permettant de créer un objet représentant une action asynchrone.

var deferred = $[Link]();

La propriété promise de l’objet renvoyé par la méthode defer permet d’accéder à la promise.

var deferred = $[Link]();

var promise = [Link];

L’objet renvoyé par la méthode defer expose des méthodes permettant de modifier l’état de la promise. La
méthode resolve résout la promise en la faisant passer dans l’état de succès. Elle prend en paramètre un objet
JavaScript qui sera envoyé en tant que résultat de la promise.

var recupererTodo = function(id) {


var deferred = $[Link]();

setTimeout(function() {
[Link]({ id : id, name : "Todo " + id});
}, 2000);

return [Link];
}

La fonction précédente permet de récupérer une tâche en fonction de son id. Elle crée une promise via le service $q et la
renvoie en tant que résultat de la fonction. L’appel à la fonction setTimeout permet de simuler un traitement asynchrone.
Au bout de deux secondes, la fonction résoudra la promise en fournissant la tâche récupérée.

La méthode reject permet au contraire de rejeter une promise en la faisant passer dans l’état d’erreur.

var recupererTodo = function(id) {


var deferred = $[Link]();

setTimeout(function() {
if(id > 0) {
[Link]({ id : id, name : "Todo " + id});
} else {
[Link]("Id de tâche invalide");
}
}, 2000);

return [Link];
}

La fonction recupererTodo a été modifiée pour que la promise soit rejetée si l’id fourni en paramètre n’est pas supérieur à

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 3-


0. Dans ce cas, un message d’erreur est passé en résultat de la promise.

La dernière méthode exposée par l’objet renvoyé par la méthode defer est notify. Cette méthode permet
d’envoyer des informations concernant l’exécution de la fonction asynchrone en gardant la promise dans l’état
d’attente de résultat.

var uploadItem = function(item) {


var deferred = $[Link]();

var progress = 0;
var interval = $interval(function() {
if (progress >= 100) {
$[Link](interval);
[Link](’Upload terminé’);
}

progress += 10;
[Link](progress + ’% effectué’);
}, 100);

return [Link];
}

La fonction précédente simule l’upload asynchrone d’un élément. La méthode notify de la promise permet d’envoyer un état
de l’avancement de l’upload.

Le service $q fournit aussi une méthode all permettant de synchroniser l’exécution de plusieurs promises en une
seule. La promise résultante sera résolue lorsque toutes les promises auront été résolues. Si au moins une des
promises est rejetée, la promise résultante sera rejetée.

$[Link]([recupererTodo(5), recupererTodo(14)]);

La promise renvoyée par la méthode all sera résolue lorsque les appels à la méthode recupererTodo seront terminés. Si
l’un de ces appels échoue, la promise renvoyée par la méthode all sera rejetée.

La dernière fonction exposée par le service $q est la fonction when. Cette fonction permet d’encapsuler un objet
JavaScript dans une promise. Si l’objet à encapsuler est une promise, la méthode when renverra simplement cette
même promise.

var promise = $[Link](recupererTodo(5));

La fonction when renvoie la promise retournée par la fonction recupererTodo.

Si l’objet à encapsuler n’est pas une promise, la fonction when renverra une nouvelle promise résolue, avec comme
résultat l’objet encapsulé.

var promise = $[Link]({ id: 0, name: "Nouveau todo"});

La fonction when renvoie une nouvelle promise résolue, avec comme résultat l’objet JavaScript.

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


Cette méthode est particulièrement utile lorsqu’il est nécessaire de travailler avec des librairies JavaScript externes
n’utilisant pas la notion de promise, et qu’il est nécessaire d’encapsuler leurs traitements dans des promises.

3. Interactions avec une promise

Pour agir lors de la modification de son état, une promise expose une méthode then. Cette méthode prend trois
paramètres : une fonction permettant d’agir lorsque la promise est résolue, une fonction permettant d’agir lorsque
la promise est rejetée et une fonction permettant de réagir lors d’une notification concernant l’exécution de l’action
asynchrone.

recupererTodo(5).then(function(todo) {
// Promise résolue
}, function(error) {
// Promise rejetée
}, function(informations) {
// Notification d’avancement
});

La méthode then d’une promise retourne une nouvelle promise. Il est ainsi possible de chaîner des appels à des
actions asynchrones simplement.

recupererTodo(5).then(recupererTodo(6)).then(recupererTodo(7));

La méthode catch d’une promise permet de définir un comportement lorsqu’elle passe dans l’état d’erreur.

recupererTodo(5).catch(function(error) {
// Promise rejetée
});

La syntaxe
catch(function(error) { ... }) est équivalente à la syntaxe then(null, function
(error) { ... }).

Il est aussi possible d’utiliser la méthode catch pour gérer les erreurs lors de plusieurs appels asynchrones
chaînés de manière centralisée.

recupererTodo(3)
.then(recupererTodo(4))
.then(recupererTodo(5))
.catch(function(error) {
// Une des promises rejetée
});

La méthode catch de l’exemple précédent sera déclenchée lorsqu’une des promises sera rejetée.

La dernière méthode fournie par une promise est la méthode finally. Elle permet d’ajouter un comportement
après qu’une promise ait été résolue ou rejetée.

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 5-


recupererTodo(5).finally(function() {
// Promise résolue ou rejetée
});

De la même manière que la méthode catch, il est possible d’utiliser la méthode finally pour exécuter un
traitement après l’exécution de plusieurs actions asynchrones.

recupererTodo(3)
.then(recupererTodo(4))
.then(recupererTodo(5))
.finally(function(error) {
// Une des promises rejetée ou toutes les promises résolues
});

Dans ce cas, la méthode finally sera déclenchée quand toutes les promises auront été résolues, ou lorsqu’une
des promises aura été rejetée.

Les mots­clés catch et finally sont réservés dans le standard EcmaScript 3, sur lequel se base JavaScript pour
le navigateur Internet Explorer 8 et les versions 2.x d’Android. Pour utiliser ces mots­clés, il faut utiliser la syntaxe
[’catch’] et [’finally’] respectivement à la place de .catch et .finally.

Pour plus d’informations concernant le service $q et les promises AngularJS, vous pouvez vous rendre à l’adresse
suivante : [Link]

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


Communication avec le serveur
Dans une application web, la communication avec le serveur se fait via des requêtes HTTP. AngularJS propose deux
services permettant de faciliter les interactions avec le serveur.

1. Service $http

Le service $http, fourni par AngularJS, permet d’effectuer des requêtes HTTP. Ce service est basé sur le
mécanisme de promise vu précédemment.

a. Effectuer une requête HTTP

Pour effectuer une requête HTTP, il faut utiliser le service $http en tant que méthode, en fournissant un objet
JavaScript de configuration décrivant la requête à effectuer :

$http({ method: ’GET’, url: ’api/posts’ });

L’objet de configuration peut posséder les propriétés suivantes :

method Verbe HTTP de la requête (GET, POST, PUT, etc.).

url URL de la requête.

params Chaîne de caractères ou objet JavaScript qui sera envoyé avec la requête en
tant que query string.

data Chaîne de caractères ou objet JavaScript qui sera envoyé dans le corps de la
requête.

headers Définit les headers de la requête.

transformRequest Fonction de transformation de la requête.

transformResponse Fonction de transformation de la réponse à la requête.

cache Définit la façon dont les requêtes GET sont mises en cache.

timeout Timeout en millisecondes ou promise annulant la requête lorsqu’elle est


résolue.

responseType Type de la réponse (JSON, XML, etc.)

Le service $http étant basé sur le mécanisme des promises, l’appel au service $http en renvoie une. Il est
possible de chaîner la requête HTTP avec les méthodes then, catch et finally, comme vu précédemment.

$http({ method: ’GET’, url: ’api/posts’ })


.then(function(data) {
// Succès
})
.catch(function(error) {
// Erreur
})
.finally(function() {
// Toujours exécutée
});

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 1-


Une réponse HTTP dont le code est un code de succès, c’est­à­dire commençant par un 2 (200, 201, etc.) résoudra
la promise. Un code d’erreur HTTP déclenchera au contraire le rejet de la promise.

Le service $http rajoute deux méthodes spécifiques à la promise renvoyée : la méthode success est appelée
en cas de succès de la requête et la méthode error est appelée en cas d’erreur de la requête.

$http({ method: ’GET’, url: ’api/posts’ })


.success(function(data) {
// Succès
}).
.error(function(error) {
// Erreur
});

Ces deux méthodes peuvent se substituer aux méthodes then et catch de la promise.

La syntaxe suivante permet d’effectuer une requête de type GET sur l’URL api/posts avec un paramètre
category.

$http({ method: ’GET’, url: ’api/posts’, params: { category:


’AngularJS’ } });

Les outils de développement de tous les navigateurs récents permettent d’afficher les requêtes effectuées. Ils
représentent un bon outil pour déboguer rapidement le résultat de l’utilisation du service $http.

b. Méthodes raccourcies

Un ensemble de méthodes sont exposées par le service $http permettant d’effectuer une requête sans avoir à
renseigner une configuration.

Les méthodes get, delete, head, jsonp permettent respectivement d’effectuer une requête HTTP de type
GET, de type DELETE, de type HEAD ou de type JSONP. Elles prennent en paramètre l’URL de la requête, et
optionnellement une configuration.

$[Link](’api/posts’, { params: { category: ’AngularJS’ } });

Le code précédent effectue une requête HTTP GET à l’URL api/posts permettant de récupérer la liste des articles de blog de la
catégorie AngularJS.

- 2- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


$[Link](’api/posts/5’);

Le code précédent effectue une requête HTTP HEAD à l’URL api/posts/5 permettant de récupérer des informations sur l’article
de blog dont l’id est 5.

$[Link](’api/posts/5’);

Le code précédent effectue une requête HTTP DELETE à l’URL api/posts/5 permettant de supprimer l’article de blog dont l’id
est 5.

$[Link]("[Link]

Le code précédent effectue une requête HTTP en utilisant le mécanisme JSONP pour récupérer des informations via une API
située dans un domaine différent.

JSONP est une technique permettant de récupérer une réponse JSON depuis un domaine différent, sans limitation
liée au cross­domain. Le principe de JSONP est d’inclure la réponse JSON dans une fonction JavaScript qui sera
exécutée par la page. Le nom de cette fonction est passé dans le paramètre callback de la query string.

Les méthodes post et put permettent respectivement d’effectuer une requête de type POST ou PUT. Elles
prennent en paramètres l’URL de la requête, le contenu à envoyer dans la requête, et optionnellement une
configuration.

$[Link](’api/posts’,
{
title : ’Les filtres AngularJS’,
resume: ’Explication des filtres AngularJS’,
content: ’Contenu de l\’article’,
category : ’AngularJS’,
tags : [’AngularJS’,’Filters’]
}
);

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 3-


Le code précédent effectue une requête HTTP POST à l’URL api/posts, en passant des informations dans le body de la
requête, permettant de créer un nouvel article de blog.

$[Link](’api/posts’, { id: 8, content: ’Contenu mis à jour de l\’article’ });

Le code précédent effectue une requête HTTP PUT à l’URL api/posts, en passant des informations dans le body de la requête,
permettant de mettre à jour un article de blog.

c. Provider $httpProvider

Le service $http est exposé par le provider


$httpProvider. Il permet d’appliquer une configuration commune
à l’ensemble des requêtes effectuées par le service $http.

L’utilisation de ce provider se fait dans la méthode config du module :

[Link](function ($httpProvider) {

});

d. Headers HTTP

- 4- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


Il est possible de définir les headers de la requête HTTP en utilisant la propriété headers d’une configuration.

$[Link](’api/posts’,
{
params: { category: ’AngularJS’ },
headers: {
’Authorization’: ’Basic YmVlcDpib29w’
}
});

L’exemple précédent effectue une requête de type GET à l’URL api/posts en fournissant un header d’autorisation.

Lors de chaque requête HTTP effectuée par le service $http, AngularJS va rajouter automatiquement les headers
suivants :

l Accept: application/json, text/plain, * / * pour toutes les requêtes.


l Content-Type: application/json pour toutes les requêtes de type POST ou PUT.

La propriété [Link] du $httpProvider permet de définir les headers pour toutes les
requêtes effectuées par le service
$http.

$[Link] = ’Basic YmVlcDpib29w’

Les propriétés [Link] et [Link] permettent, quant à elles, de définir


les headers respectivement pour toutes les requêtes de type POST et pour toutes les requêtes de type PUT
effectuées par le service $http.

e. Transformation de la requête et de la réponse

Lorsqu’une requête est effectuée par $http, le mécanisme de transformation permet d’ajouter un traitement
chargé de modifier la requête HTTP avant qu’elle ne soit envoyée, ou chargé de modifier la réponse avant qu’elle
ne soit renvoyée à la promise par $http.

Sur chacune des requêtes, AngularJS applique déjà des transformations. Avant l’envoi d’une requête, si la
propriété data d’une configuration contient un objet JavaScript, AngularJS va sérialiser cet objet au format JSON.
De la même manière, à la réception d’une réponse, si elle contient du JSON, AngularJS la désérialisera.

Les propriétés [Link] et [Link] du provider


$httpProvider sont des tableaux contenant la liste des fonctions de transformations appliquées à toutes les
requêtes HTTP. Pour ajouter sa propre fonction de transformation de requête ou de réponse, il suffit de l’ajouter à
l’une de ces propriétés :

$[Link](function (data,
headers){
[Link]("transform Request");
return data;
});

$[Link](function (data,

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 5-


headers){
[Link]("transform Response");
return data;
});

Chaque fonction de transformation prend en paramètre les données et les headers de la requête ou de la réponse
et doit renvoyer les données transformées.

Il est possible d’écraser toutes les fonctions de transformations précédemment définies en assignant directement
à ces propriétés une fonction de transformation. De cette manière, seule la transformation définie sera appliquée.

$[Link] = function (data,


headers){
[Link]("transform Request");
return data;
};

$[Link] = function (data,


headers){
[Link]("transform Response");
return data;
};

Il est aussi possible de définir les transformations sur une requête HTTP en particulier. Pour cela, il faut utiliser les
propriétés transformRequest et transformResponse de la configuration de la requête.

$[Link](’api/posts’,
{
params: { category: ’AngularJS’ },
transformRequest: function(data, headers) {
[Link]("transform Request");
return data;
},
transformResponse: function(data, headers) {
[Link]("transform Response");
return data;
}
});

La requête HTTP de l’exemple précédent remplace les transformations définies par $httpProvider par ses propres
transformations.

f. Cache

Le service $http possède un mécanisme de cache permettant de stocker les réponses du serveur aux requêtes
de type GET. De cette manière, la prochaine fois qu’une requête de type GET, ayant déjà été exécutée, sera
rejouée, le service $http ira chercher la réponse directement depuis son cache au lieu de contacter le serveur.
Pour activer ce mécanisme, il faut positionner la propriété cache d’une configuration à true.

$[Link]("/posts", { cache: true });

- 6- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


L’activation du cache pour toutes les requêtes HTTP se fait via la propriété [Link] du provider
$httpProvider.

$[Link] = true;

Ce mécanisme s’appuie sur le service $cacheFactory, qui va créer un cache nommé "$http" et contenant
toutes les réponses aux requêtes. Pour récupérer manuellement un élément du cache, il suffit d’accéder au cache
via le service $cacheFactory puis de récupérer la réponse en spécifiant l’URL de la requête.

var $httpCache = $[Link]("$http");


var cachedData = $[Link]("/posts");

Lorsque le besoin se fait sentir, il est possible de ne pas utiliser le cache par défaut en spécifiant un autre cache à
utiliser. Pour cela, il faut assigner à la propriété cache le cache à utiliser.

var lruCache = $cacheFactory(’lruCache’, { capacity: 5 });


$[Link]("/posts", { cache: lruCache });

Dans l’exemple précédent, un nouveau cache de type LRU (Least Recently Used) est créé avec une capacité de 5. Ce cache
est ensuite utilisé dans le cadre de la requête HTTP.

La configuration d’un cache spécifique pour toutes les requêtes HTTP peut se faire en assignant le cache à la
propriété [Link] du provider :

$[Link] = lruCache;

g. Intercepteurs

Les intercepteurs permettent d’ajouter des comportements communs à toutes les requêtes HTTP effectuées par le
service $http. Ils permettent par exemple de gérer de manière globale les erreurs ou les mécanismes
d’authentification.

La déclaration d’intercepteurs se fait via la propriété interceptors du provider $httpProvider, en


fournissant une fonction factory pouvant déclarer des dépendances et créant un objet contenant au moins l’une
des propriétés suivantes :

$[Link](function($q) {
return {
’request’: function(config) {
return config;
},

’requestError’: function(rejection) {
return $[Link](rejection);
},

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 7-


’response’: function(response) {
return response;
},

’responseError’: function(rejection) {
return $[Link](rejection);
}
};
});

Les intercepteurs agissent dans quatre situations différentes :

l request lors de la création de la requête afin de modifier la configuration. La fonction associée doit renvoyer un
objet de configuration ou une promise contenant la configuration.

l requestError lorsqu’une requête n’a pas pu être envoyée. La fonction associée prend en paramètre la cause
de l’erreur.

l response lors de la réception d’une réponse à une requête HTTP. La fonction associée doit renvoyer une réponse
ou une promise contenant une réponse.

l responseError lorsqu’une réponse en erreur est reçue. La propriété status de l’objet rejection passé
en paramètre de la fonction contient le code d’erreur HTTP de la réponse.

Voici un exemple d’intercepteur agissant lors de la réception d’une réponse en erreur :

$[Link](function ($q, $location, $rootScope,


$injector) {
return {
’responseError’: function (rejection) {
if ([Link] === 401) {
var userService = $[Link]("userService");
var $http = $[Link]("$http");

return [Link]()
.then(function (data) {
[Link]["Authorization"] = "Bearer " + data;
return $http([Link]);
}, function () {
$rootScope.$broadcast("connectionExpired");
$[Link](’/connexion’);
return $[Link](rejection);
});
} else if ([Link] === 403) {
var applicationService = $[Link]("applicationService");
var $http = $[Link]("$http");

return [Link]()
.then(function (data) {
[Link]["app-token"] = data;
return $http([Link]);
});
}

- 8- © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


return $[Link](rejection);
}
};
});

Le code précédent déclare un intercepteur permettant de gérer les erreurs lors de requêtes HTTP.

Si le code d’erreur HTTP est 401, c’est­à­dire accès non autorisé à une ressource à cause de l’authentification, l’intercepteur
va appeler la méthode renewToken du service userService, chargé d’aller récupérer un nouveau jeton
d’authentification. Si la récupération du jeton se fait avec succès, le header Authorization de la requête ayant échoué
sera mis à jour et la requête sera réexécutée. Si par contre la récupération du jeton échoue, l’évènement
connectionExpired sera broadcasté, pour propager l’information indiquant que l’utilisateur n’est plus connecté, et
l’utilisateur sera redirigé vers la page de connexion.

Si le code d’erreur HTTP est 403, c’est­à­dire accès non autorisé à une ressource pour une cause autre que l’authentification,
l’intercepteur va appeler la méthode getToken du service applicationService, chargé de récupérer un nouveau
token d’accès pour l’application. Le header app-token de la requête ayant échoué sera mis à jour et la requête sera
réexécutée.

h. Timeout

La propriété timeout d’une configuration permet de définir la manière dont le timeout de la requête va être géré.

Cette propriété peut prendre une valeur entière, correspondant au nombre de millisecondes après lesquelles le
timeout de la requête sera déclenché.

$http({
method: ’GET’, url: ’api/posts’,
params: { category: ’AngularJS’ },
timeout: 2000
});

Un timeout de deux secondes est déclaré sur l’appel précédent.

Lorsqu’une requête passe en timeout, la promise associée est rejetée.

Cette propriété peut aussi prendre comme valeur une promise. Lorsque cette promise est résolue, le timeout de la
requête est déclenché.

[Link]("blogController", function ($scope, $http, $q)


{
var canceller = $[Link]();

$[Link] = function () {
[Link]();
}

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 9-


$http({
method: ’GET’, url: ’api/posts’,
params: { category: ’AngularJS’ },
timeout: [Link]
});
});

Le contrôleur précédent crée une promise qui est utilisée en tant que timeout d’une requête HTTP et expose une méthode
cancelQuery. À l’appel de cette méthode, la promise liée au timeout est résolue ce qui annulera la requête HTTP.

De cette manière, il est possible de gérer plus finement le timeout et imaginer des scénarios où une seule requête
simultanée pourra être effectuée sur une URL donnée.

[Link]("rechercheVilleService", function ($http, $q) {


var self = this;
[Link] = null;

return {
getVilles: function (villeOuCodePostal) {
if ([Link]) {
[Link]("other request in
progress");
}

var deferred = $[Link]();


[Link] = $[Link]();

$[Link]("/villes?search=" + villeOuCodePostal,
{ timeout: [Link] })
.success(function (villes) {
[Link]({ villes: villes });
});

return [Link];
}
};
});

Le service précédent expose une méthode getVilles, permettant de récupérer une liste de villes en fonction d’un nom ou
d’un code postal, en effectuant une requête HTTP.

Pour éviter que plusieurs recherches simultanées ne soient effectuées, cette méthode lie le timeout de la requête HTTP à une
promise. À chaque appel de la méthode, si la promise est définie, c’est­à­dire qu’une requête HTTP est en cours, elle sera
résolue pour annuler la requête HTTP. Puis la nouvelle requête HTTP, avec un timeout lié à une nouvelle promise, sera
effectuée.

i. Encapsulation des appels dans un service

Grâce au mécanisme d’IoC d’AngularJS, le service $http est injectable dans les différents éléments d’une

- 10 - © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


application, que ce soit dans un contrôleur, une directive, un service, etc.

Dans le but de garder une organisation structurée, il est recommandé de ne pas utiliser le service $http
directement dans un contrôleur mais de créer un service chargé d’encapsuler les appels HTTP d’un certain domaine
fonctionnel.

[Link]("userService", function($http) {
return {
getUserInformations: function() {
return $[Link]("/user/infos");
},
login: function(login, password) {
...
},
logoff: function() {
...
}
};
});

Le service précédent expose plusieurs fonctions. Chaque fonction encapsule les appels HTTP nécessaires pour effectuer une
action, comme connecter l’utilisateur, le déconnecter ou récupérer ses informations.

Pour plus d’informations concernant le service $http, vous pouvez vous rendre à l’adresse suivante :
[Link]

2. Service $resource

Le module ngResource d’AngularJS fournit le service $resource, permettant de communiquer avec le serveur.
Pour utiliser ce module, il faut référencer le script [Link], puis définir ngResource comme dépendance
du module principal.

<script type=”text/javascript" src="[Link]


ajax/libs/angularjs/1.3.4/[Link] " />

[Link]("monApp", ["ngResource"]);

Contrairement au service $http, qui permet d’effectuer des requêtes en spécifiant une URL et un verbe HTTP, ainsi
qu’éventuellement une configuration, $resource est un service plus haut niveau. Il permet d’encapsuler dans une
ressource, correspondant techniquement à un objet JavaScript, un service REST.

REST (Representational State Transfer) est un style d’architecture permettant de structurer les services web, en se
basant sur le protocole HTTP. Le principe de cette architecture est de se baser sur l’URL ainsi que sur le verbe HTTP
pour déterminer l’opération à effectuer. Le verbeGET permet de lire des ressources, le verbe POST d’en ajouter, le
verbe PUT d’en modifier et le verbe DELETE d’en supprimer.

Grâce à $resource, l’interaction avec le service REST se fera de manière transparente, via une ressource, sans
avoir à spécifier ni l’URL ni le verbe HTTP.

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 11 -


a. Création d’une ressource

Pour pouvoir encapsuler un service REST, il faut créer une ressource en utilisant le service $resource en tant
que fonction. Cette fonction attend en paramètre l’URL paramétrée du service, chaque paramètre devant être
préfixé par :, et renvoie une classe JavaScript contenant l’encapsulation du service REST.

var User = $resource(’/:version/users/’);

Dans l’exemple précédent, le service


$resource est utilisé pour créer une ressource via une URL contenant un paramètre
version. L’objet User renvoyé correspond à une classe JavaScript encapsulant le service REST.

Le second paramètre à renseigner optionnellement correspond aux paramètres par défaut utilisés pour construire
l’URL.

var User = $resource(’/:version/users/’, {version : ’v1’});

Dans l’exemple précédent, le paramètre version de l’URL est défini à v1. L’URL utilisée sera donc /v1/users.

Si la valeur du paramètre est préfixée par @, la valeur pour ce paramètre sera automatiquement extraite depuis la
propriété correspondante de la ressource, lorsqu’une action sera appelée sur la ressource.

var User = $resource(’/users/:userId’, {userId: ’@id’});

Dans l’exemple précédent, l’URL déclare un paramètre userId initialisé par la propriété id. À chaque fois qu’une action
sera effectuée sur une ressource, sa propriété id sera automatiquement utilisée pour renseigner le paramètre userId de
l’URL.

b. Récupération des ressources

Une fois la ressource créée, plusieurs méthodes permettant d’interagir avec le service REST seront exposées.

La première méthode est la méthode query permettant de récupérer une liste de ressources. Le premier
paramètre de cette méthode correspond aux paramètres à envoyer avec la requête et le second correspond au
callback appelé lorsque la réponse aura été reçue.

var User = $resource(’/users/:userId’, {userId: ’@id’});

[Link]({}, function (users) {


});

Le code précédent crée une ressource puis utilise la méthode query pour récupérer la liste de toutes ces ressources.

L’appel à cette méthode déclenche l’exécution d’une requête HTTP de type GET.

- 12 - © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


Le code précédent déclenche l’exécution d’une requête GET sur l’URL /users.

La réponse à la requête précédente contiendra la liste des ressources, dans l’exemple la liste des utilisateurs.

Si des paramètres sont passés, ils seront utilisés dans l’URL de la requête ou dans la query string, en fonction de
la configuration de la ressource.

[Link]({page: 2}, function (users) {


});

L’appel précédent spécifie un paramètre page égal à 2.

Le paramètre page n’étant pas défini dans l’URL de la ressource, il sera envoyé par la query string.

La seconde méthode exposée est la méthode get, permettant de récupérer une ressource. De la même manière
que la méthode query, elle prend en paramètre une liste de paramètres à envoyer avec la requête et un callback.

[Link]({ userId: ’412DC20B-8E37-46E8-959C-71EDA9059B7D’},


function(user) {
});

Le code précédent utilise la méthode get de la ressource User pour récupérer l’utilisateur dont l’id est égal à 412DC20B­
8E37­46E8­959C­71EDA9059B7D

L’appel à cette méthode déclenche l’exécution d’une requête GET.

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 13 -


Le paramètre userId étant défini dans l’URL de la ressource, il sera utilisé pour construire l’URL de la requête GET qui sera
exécutée.

La réponse à la requête précédente contiendra une ressource, dans l’exemple l’utilisateur dont l’id est égal à 412DC20B­8E37­
46E8­959C­71EDA9059B7D.

c. Interaction avec une ressource

Chaque ressource récupérée, via les méthodes get ou query, sera un objet JavaScript contenant des méthodes
permettant d’interagir avec cette ressource.

La méthode $save permet de créer ou de mettre à jour une ressource.

var user = new User();


[Link] = ’Sébastien’;
[Link] = ’Ollivier’;
[Link] = ’[Link]@[Link]’;
[Link] = true;
user.$save().then(function(createdUser) {
});

Le code précédent crée une nouvelle ressource, via l’objet User, puis appelle la méthode $save permettant de la
sauvegarder côté serveur.

L’appel à cette méthode déclenche l’exécution d’une requête POST, contenant dans son body les données de la
ressource et retournant une promise contenant la ressource mise à jour.

- 14 - © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


L’appel à la méthode $save dans l’exemple précédent provoque l’exécution d’une requête POST. Les propriétés de
l’utilisateur sont passées dans le body de la requête.

[Link]({ userId: ’412DC20B-8E37-46E8-959C-71EDA9059B7D’},


function(user) {
[Link] = ’[Link]@[Link]’;
user.$save().then(function(updatedUser) {
});
});

Le code précédent récupère une ressource via la méthode [Link]. Dans le callback, cette ressource est modifiée puis un
appel à la méthode $save est effectué afin de sauvegarder les modifications côté serveur.

Les méthodes $delete et $remove permettent quant à elles de supprimer une ressource.

[Link]({ userId: ’412DC20B-8E37-46E8-959C-71EDA9059B7D’},


function(user) {
user.$delete();
});

Le code précédent récupère une ressource via la méthode [Link]. Dans le callback, cette ressource est supprimée via
l’appel à $delete.

L’appel à cette méthode déclenche l’exécution d’une requête DELETE.

L’appel à la méthode $delete dans l’exemple précédent provoque l’exécution d’une requête DELETE. Étant donné la

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 15 -


configuration définie précédemment, la propriété id de la ressource sera utilisée pour initialiser le paramètre userId de
l’URL.

d. Méthodes spécifiques

Si le service REST expose des méthodes spécifiques, il est possible de les déclarer dans la ressource, en utilisant
le troisième paramètre de la fonction $resource.

Ce paramètre représente la liste des méthodes spécifiques à déclarer, avec pour chacune son nom suivi d’une
configuration. La configuration correspond à la configuration qui a été vue précédemment pour le service $http,
avec notamment les propriétés method, params, transformRequest, timeout, etc. avec en plus une
propriété isArray permettant de définir si la méthode renvoie une ressource ou une liste de ressources.

$resource(’/users/:userId’, {userId:’@id’},
{
’enable’: {method: ’PUT’, params: {’enabled’: true},
isArray : false} ,
’disable’: {method: ’PUT’, params: {’enabled’: false},
isArray : false}
} );

Le code précédent déclare une ressource sur l’URL


/users, avec un paramètre userId. Le troisième paramètre passé
permet de définir une méthode nommée
enable qui déclenchera une requête PUT, avec le paramètre enabled à true. Une
deuxième méthode, nommée disable, est déclarée sur le même modèle. Les paramètres isArray à false permettent de
déclarer que la réponse aux requêtes HTTP contiendra l’élément modifié, et non une liste.

L’utilisation de ces méthodes se fait en appelant la fonction de la ressource possédant le même nom, préfixé par
un $.

user.$enable();

Le code précédent fait appel à la méthode $enable d’une ressource.

L’appel à la méthode $enable a déclenché l’exécution d’une requête PUT avec en query string le paramètre enabled à
true et dans l’URL l’id de l’utilisateur.

De la même manière que les autres méthodes d’une ressource, les méthodes spécifiques retournent des promises,
contenant une ressource ou une liste de ressources, en fonction de la valeur du paramètre de configuration
isArray.

user.$enable().then(function(user) {
});

e. Encapsulation dans un service

- 16 - © Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN


Pour les mêmes raisons que le service $http, il est préférable d’encapsuler l’utilisation de $resource dans un
service :

[Link](’User’, function($resource){
return $resource(’/users/:userId’, {userId:’@id’});
});

Pour plus d’informations concernant le service $resource, vous pouvez vous rendre à l’adresse suivante :
[Link]

© Editions ENI – Tous droits réservés – Copie personnelle de NOEMIE PERRIN - 17 -

Vous aimerez peut-être aussi