05. Les services
Nous allons dans cette leçon, étudier la manière de créer des services avec Angular; nous en profiterons pour agrémenter notre application d’un service de gestion des séries, ce qui simulera l’appelle à une API.
Plusieurs méthodes
Il existe 5 fonctions pour créer des services dans Angular, la différence entre elle peut parfois paraitre subtile notamment si vous débutez en JavaScript. Je vous conseille donc dans un premier temps d’utiliser provider() lorsque votre service aura besoin d’être configuré (comme nous l’avons fait pour les routes) sinon utilisez service().
- value() service simple dans lequel on ne pourra pas injecter d'autres services
- constant() comme value mais ne peut pas être modifié par la suite
- service() crée le service en faisant un new sur la fonction définie
- factory() crée le service en exécutant la fonction définie
- provider() crée un service qu'il est possible de configurer
Ci après, en exemple, le même service déclaré de 3 manières différentes:
var app = angular.module('showthequeApp', []);
app.service('userManager', function() {
this.getName = function() {
return 'User: manu';
};
});
app.factory('userManager', function() {
return {
getName: function() {
return 'User: manu';
}
};
});
app.provider('userManager', function() {
this.name = 'inconnu';
this.$get = function() {
var name = this.name;
return {
getName: function() {
return 'User: ' + name;
}
}
};
this.setName = function(name) {
this.name = name;
};
});
app.config(['userManagerProvider', function(userManagerProvider){
userManagerProvider.setName('manu');
}]);
Notre service de gestion des séries
Dans un premier temps, pour simplifier, plutôt que de créer un WebService pour gérer les données de notre application, nous allons les mettre en dur dans un fichier JSON que notre service appellera.
Pour cela, créons le fichier src/api/shows.js et plaçons y quelques données de test comme suit :
{
"entities": [
{
"id": 1,
"title": "Sense 8",
"year": 2015,
"seasons": [
{
"number": 1,
"episodes": [
{
"number": 1,
"view": true
},
{
"number": 2
},
{
"number": 3
},
{
"number": 4
}
]
},
{
"number": 2,
"episodes": [
{
"number": 1
},
{
"number": 2,
"view": true
}
]
}
]
},
{
"id": 2,
"title": "Ascension",
"year": 2012
},
{
"id": 3,
"title": "Utopia",
"year": 2001
}
]
}
Puis, créons notre premier service qui fera appel au service $http fourni par Angular pour faire des requêtes web. Nous l’utiliserons pour récupérer notre jeu de données contenu dans le fichier shows.js créé précédemment.
// src/modules/show/services/showService.js
'use strict';
// pour travailler en local étant donné que nous n'avons pas pour le moment de base de données
var _shows = undefined;
module.service('showService', ['$q', '$http', function ($q, $http) {
var getShows = function () {
// création d'une promise pour travailler en asynchrone
var deferred = $q.defer();
// si _shows contient déjà des données nous pouvons directement les retourner
if (_shows) {
deferred.resolve(_shows);
}
// sinon il faut les charger depuis le fichier json
else
{
$http.get('/src/api/shows.js').then(
// si pas d'erreur
function (data) {
_shows = data.entities;
deferred.resolve(_shows);
},
// si une erreur
function (response) {
deferred.reject(response);
}
);
}
// on retourne la promise
return deferred.promise;
};
// methode public accessible depuis le service
return {
getShows: getShows
};
}])
Le service $http offre plusieures méthodes dont get() et post() qui permettent respectivement d’envoyer des requêtes en GET ou en POST. Chacunes de ces méthodes retournent une promise.
Les promise contiennent plusieurs méthodes dont then() qui prend en paramètre deux fonctions; une qui sera exécutée s’il n’y a pas eu d’erreur et l’autre s’il y a une erreur.
Nous aurions pu retourner directement le résultat de la méthode get() mais dans l’exemple j’ai souhaité mettre en cache le résultat, afin de pouvoir par la suite, ajouter ou enlever des éléments sans que nous ayons réellement de base de données.
Pour cela, j’ai créé une promise intermédiaire grâce au service $q et la méthode defer(). Ce nouvel objet contient la promise (deferred.promise) une méthode à appeler en cas de succès (deferred.resolve) et une en cas d’erreur (deferred.reject).
Conclusion
Maintenant que nous avons des donnée, nous allons pouvoir dans la prochaine leçon, les utiliser, pour créer notre premier page dans le module show qui va lister les séries.