angularjs definition



AngularJS utilisant $ rootScope en tant que magasin de données (4)

J'ai une idée pour mon application AngularJS et je suis curieux de savoir si la communauté AngularJS le jugerait acceptable de le faire de cette façon ...

En bref, je me connecte à une API de données et affiche mes résultats sur la page. J'ai créé un service angulaire qui crée un magasin de données sur $ rootScope.DataStore. J'ai également une méthode de service qui met à jour le stock de données avec les données renvoyées par un point de terminaison API. Si je demande le point de terminaison de l'API "produits" à partir de l'intérieur de mon contrôleur avec DataStore.update ("produits"), ceci mettra à jour $ rootScope.DataStore.products avec mes données de produit. Maintenant, dans la vue partielle, tout ce que j'ai à faire est de dire ng-repeat = "produit dans DataStore.products" pour afficher mes données, et peu importe la portée du contrôleur dans lequel je me trouve. Donc, essentiellement, mon DataStore est ma seule source de vérité.

Ce que j’ai le sentiment d’obtenir de cette méthode est facile à suivre, tout comme la sémantique et le codage minimal des contrôleurs. Ainsi, chaque fois que le DataStore est mis à jour, tout ce qui est lié à DataStore est également mis à jour.

Est-ce que cela mettrait trop de charge sur le cycle de digest $ rootScope, ou est-ce simplement une façon étrange de le faire? Ou est-ce une façon totalement géniale? :) Tous les commentaires sont les bienvenus.

https://ffff65535.com


Cette question est abordée dans la FAQ AngularJS citée ici:

Parfois, vous souhaitez que certaines données soient globales pour l'ensemble de l'application. Pour ceux-ci, vous pouvez injecter $ rootScope et y définir des valeurs comme toute autre étendue. Comme les portées héritent de la portée racine, ces valeurs seront disponibles pour les expressions attachées à des directives telles que ng-show, tout comme les valeurs de votre portée locale $.

Il semble que l'équipe encourage l'utilisation de $rootScope cette façon, avec cette mise en garde:

Bien sûr, l'état global est nul et vous devriez utiliser $ rootScope avec parcimonie, comme vous le feriez (espérons-le) avec des variables globales dans n'importe quelle langue. En particulier, ne l'utilisez pas pour le code, mais uniquement pour les données. Si vous êtes tenté de mettre une fonction dans $ rootScope, il est presque toujours préférable de la placer dans un service qui peut être injecté là où c'est nécessaire et plus facilement testé.

Inversement, ne créez pas un service dont le seul but dans la vie est de stocker et de restituer des bits de données.

Cela ne met pas trop de charge sur le cycle $digest (qui implémente le contrôle de base pour vérifier la mutation des données) et ce n'est pas une façon étrange de faire les choses.

EDIT: Pour plus de détails sur les performances, voir cette réponse de Misko (AngularJS dev) ici sur SO: Comment fonctionne la liaison de données dans AngularJS? Notez spécifiquement la section sur les performances.


D'après mon expérience, utiliser la méthode $ rootScope pour stocker la partie de mon modèle de données commune à tous les ngViews de mon application est le moyen le plus pratique.

<div>{{mymodel.property}}</div>

est pour moi plus lisible et plus court que

<div>{{getPropertyModel()}}</div>

avec le javascript

app.factory('MyModel', function(){
    return {
        getModel: function() { ... },
        setModel: function(m) { ... },
    }
});

app.controller('ctrl', ['$scope', 'MyModel', function($scope, MyModel){
    $scope.getPropertModel = function() {
        return MyModel.getModel().property;
    };
}]);

Si l’on utilise un service ou une mémoire cache, chaque accès au modèle dans le modèle html devient une fonction moins lisible qu’un accès à une propriété du rootScope. L'utilisation de $ rootScope donne moins de code, donc moins d'erreurs et moins de tests.

Bien sûr, seule la partie commune de tous les ngView est stockée dans $ rootScope. Le reste du modèle est stocké dans la portée locale $.

Les montres d'une fonction sont également plus lentes que celles des propriétés d'objet. En termes de performances, $ rootScope est également préférable.


Je suppose que je ne suis pas sûr de savoir pourquoi vous devez utiliser rootScope? La durée de vie d'une instance de service correspond également à l'ensemble de l'application. Ainsi, les schémas / sémantiques de données que vous utilisez pourraient également être stockés dans le service lui-même et seraient partagés entre les contrôleurs. Aucune de ces méthodes ne survit cependant à l'actualisation, contrairement à l'utilisation d'un stockage local.

Le reste ressemble à une approche de chargement paresseuse. Où le service est le seul à savoir "savoir" si les données ont été chargées à partir de la télécommande et les renvoient si elles sont déjà mises en cache et les mettent en cache et les renverront si ce n'est pas le cas? Si je comprends bien cette partie, c’est un bon modèle.

edit: Ici, je suis en train de prendre une approche similaire au chargement paresseux, notez que le cache est juste dans le service même:

angular.module('HN_Reddit_Mashup.Services', [])
    .factory('HackerNews', function($http) {
        var HackerNewsCache = {};
        return {
            get: function(url) {
                return HackerNewsCache[url] ||
                    (HackerNewsCache[url] = $http.jsonp("http://api.thriftdb.com/api.hnsearch.com/items/_search?q=" + url +     "&callback=JSON_CALLBACK"));
            },                
        };
    })

Pour apaiser toutes les parties, pourquoi ne pas utiliser simplement $ cacheFactory. Cela permet aux services de demande de données d'être sans état et, en gros, d'être un getter et un setter. J'admettrai que conserver les données sur le $ rootScope ou qu'une propriété du service est pratique mais se sent mal. L'utilisation de $ cacheFactory est également très facile.

Commencez par créer un service de cache:

angular.module('CacheService', ['ng'])
    .factory('CacheService', function($cacheFactory) {
    return $cacheFactory('CacheService');
});

Incluez le fichier js dans votre app.js, puis insérez-le dans la déclaration de votre application:

var MyApp = angular.module('MyApp', ['CacheService']);

Injectez-le dans le service, utilisez-le comme suit:

'use strict'

MyApp.factory('HackerNewsService', function(CacheService) {
    return {
        getNews: function(key) {
            var news = CacheService.get(key);

            if(news) {
                return news;
            }

            return null;
        },
        setNews: function(key, value) {
            CacheService.put(key, value);
        },
        clearNews: function(key) {
            CacheService.put(key, '');
        }
    };
});

Maintenant, tout ce que vous avez à faire est d’injecter votre HackerNewsService dans votre contrôleur et de l’utiliser en appelant les méthodes que nous avons créées. Par exemple:

HackerNewsService.setNews('myArticle', {headline: 'My Article', body: 'This is the body'});
$scope.article = HackerNewsService.getNews('myArticle');




angularjs