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().

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.