在angularjs服务中缓存数组

时间:2014-04-07 21:49:32

标签: javascript arrays angularjs caching

我是AngularJS的新手,我仍然试图利用服务将数据提取到我的应用程序中。

我正在寻找一种方法来缓存$http.get()的结果,这将是一个JSON数组。在这种情况下,它是一个静态的事件列表:

[{ id: 1, name: "First Event"}, { id: 2, name: "Second Event"},...]

我正在使用一项服务来缓存这些结果:

appServices.service("eventListService", function($http) {
    var eventListCache;

    this.get = function (ignoreCache) {

        if (ignoreCache || !eventListCache) {
            eventListCache = $http.get("/events.json", {cache: true});
        }

        return eventListCache;
    }


});

现在从我能理解的情况来看,我正在回复一个"承诺"来自$http.get函数,我在控制器中添加了一个成功的回调函数:

appControllers.controller("EventListCtrl", ["$scope", "eventListService", 
    function ($scope, eventListService) {
        eventListService.get().success(function (data) { $scope.events = data; });
    } 
]);

这对我来说很好。我要做的是向eventListService添加一个事件,以从eventListCache中提取特定事件对象。

appServices.service("eventListService", function($http) {
    var eventListCache;

    this.get = function (ignoreCache) { ... }

    //added
    this.getEvent = function (id) {
         //TODO: add some sort of call to this.get() in order to make sure the 
         //eventListCache is there... stumped
    }        
});

我不知道这是否是接近缓存的最佳方式,或者这是一件愚蠢的事情,但我试图从一个可能缓存或不缓存的数组中获取单个对象。或者我可能应该调用原始事件并将对象拉出控制器中的结果数组。

2 个答案:

答案 0 :(得分:3)

你走在正确的轨道上。 Angularjs中的服务是singeltons,因此使用它来缓存你的$ http请求很好。如果你想在你的服务中公开几个函数,我会做这样的事情。我使用Angularjs中的$ q promise / deferred服务实现来处理asynchronus http请求。

appServices.service("eventListService", function($http, $q) {
    var eventListCache;

    var get = function (callback) {
        $http({method: "GET", url: "/events.json"}).
            success(function(data, status) {
                eventListCache = data;
                return callback(eventListCache);
            }).
        }
    }

    return {
        getEventList : function(callback) {
            if(eventListCache.length > 0) {
                 return callback(eventListCache);
            } else {
                var deferred = $q.defer();
                get(function(data) {
                    deferred.resolve(data);
                }
                deferred.promise.then(function(res) {
                    return callback(res);
                });
            }
        },
        getSpecificEvent: function(id, callback) {
            // Same as in getEventList(), but with a filter or sorting of the array
            // ...
            // return callback(....);
        }
    }
});

现在,在您的控制器中,您所要做的就是这个;

appControllers.controller("EventListCtrl", ["$scope", "eventListService", 
    function ($scope, eventListService) {

         // First time your controller runs, it will send http-request, second time it 
         // will use the cached variable
         eventListService.getEventList(function(eventlist) {
             $scope.myEventList = eventlist;
         });

         eventListService.getSpecificEvent($scope.someEventID, function(event) {
             // This one is cached, and fetched from local variable in service
             $scope.mySpecificEvent = event;
         });
    } 
 ]);

答案 1 :(得分:1)

你走在正确的轨道上。这里有一点帮助:

appServices.service("eventListService", function($http, $q) {
    var eventListCache = [];

    function getList(forceReload) {
        var defObj = $q.defer(), listHolder;

        if (eventListCache.length || forceReload) {
            listHolder= $http.get("/events.json", {cache: true});
            listHolder.then(function(data){
                eventListCache = data;
                defObj.resolve(eventListCache);
            });
        } else {
             defObj.resolve(eventListCache);
        }

        return defObj.promise;
    }

    function getDetails(eventId){
        var defObj = $q.defer();

        if(eventId === undefined){
            throw new Error('Event Id is Required.');
        }

        if(eventListCache.length === 0){
            defObj.reject('No Events Loaded.');
        } else {
            defObj.resolve(eventListCache[eventId]);
        }

        return defObj.promise;
    }

    return {
        eventList:getList,
        eventDetails:getDetails
    };
});

然后,在您的控制器中,您可以像这样处理它:

appControllers.controller(“EventListCtrl”,[“$ scope”,“eventListService”,     function($ scope,eventListService){         var eventList = eventListService.getList();         eventList.then(功能(数据){             $ scope.events = data;         });

    $scope.getEventsList = function(reloadList){
        eventList = eventListService.getList(reloadList);
        eventList.then(function(data){
            $scope.events = data;
        });
    };

    $scope.getEventDetails = function(eventID){
        var detailsPromise = eventListService.getDetails(eventID);
        detailsPromise.then(function(data){
            $scope.eventDetails = data;
        }, function(reason){
           window.alert(reason);
        });
    }
} 

]);

这样,您的事件在控制器首次加载时加载,然后您可以选择通过传入布尔值来请求新列表。获取事件详细信息也由内部承诺处理,以便在不产生破坏性错误的情况下为您提供一些错误处理。