AngularJS服务存储$ http结果以防止重新生成---有更好的方法吗?

时间:2013-08-09 00:39:54

标签: angularjs angular-services angular-http

设置:我希望有一个服务,多个控制器可以查询使用$ http提取的数据。最初的解决方案是使用建议here的承诺。

问题:每次控制器查询服务时,服务都会返回$ http承诺,从而导致多次查询只是一次又一次地从远程服务器提取相同的数据。

解决方案:服务功能返回数据或下面的承诺。并且由控制器来检查并采取相应的行动。

app.factory('myService', function($http) {
    var items = [];
    var myService = {
        getItems: function() {
            // if items has content, return items; otherwise, return promise.
            if (items.length > 0) {
                return items;
            } else {     
                var promise = $http.get('test.json').then(function (response) {
                    // fill up items with result, so next query just returns items.
                    for(var i=0;i<response.data.length;i++){
                        items.push(response.data[i]);
                    }
                    return items;
                });
                // Return the promise to the controller
                return promise;
            }
     };
     return myService;
});

因此,当控制器需要该数据时,控制器就会执行以下操作:

app.controller('MainCtrl', function( myService,$scope) {
    var promiseOrData = myService.async();
    // Check whether result is a promise or data.
    if ( typeof promiseOrData.then === 'function'){
        // It's a promise.  Use then().
        promiseOrData.then( function(data ){
            $scope.data = data;
        });
    } else {
        // It's data.
        $scope.data = data;
    }
});

所以问题是:有更好的方法吗?对于许多控制器,这种方法会有很多重复的代码。理想情况下,控制器只是直接在服务中查询数据。

谢谢!

2 个答案:

答案 0 :(得分:12)

$ http返回一个promise,我们可以使用它而不是用$ q创建一个新的。一旦承诺得到解决,我们就可以继续回复。

.factory('myService', ['$http','$q', function($http, $q) {
    var items = [];
    var last_request_failed = true;
    var promise = undefined;
    return {
        getItems: function() {
            if(!promise || last_request_failed) {
                promise = $http.get('test.json').then(
                function(response) {
                    last_request_failed = false;
                    items = response.data;
                    return items;
                },function(response) {  // error
                    last_request_failed = true;
                    return $q.reject(response);
                });
            }
            return promise;
        },
    };
}])

在您的控制器中:

myService.getItems().then( 
    function(data) { $scope.data = data; }
);

答案 1 :(得分:1)

创建自己的承诺,解析为缓存数据或获取的数据。

app.factory('myService', function($http, $q) {
    var items = [];
    var myService = {
        getItems: function() {
            var deferred =  $q.defer();

            if (items.length > 0) {
                 //resolve the promise with the cached items
                deferred.resolve(items);
            } else {     
                $http.get('test.json').then(function (response) {
                    // fill up items with result, so next query just returns items.
                    for(var i=0;i<response.data.length;i++){
                        items.push(response.data[i]);
                    }
                    //resolve the promise with the items retrieved
                    deferred.resolve(items);
                },function(response){
                   //something went wrong reject the promise with a message
                   deferred.reject("Could not retrieve data!"); 
                });


            }
         // Return the promise to the controller
         return deferred.promise;
     };
     return myService;
});

然后消耗控制器中的承诺。

app.controller('MainCtrl', function( myService,$scope) {
    var promiseOrData = myService.getItems();

        promiseOrData.then( function(data){
            $scope.data = data;
        },
        function(data){
            // should log "Could not retrieve data!"
            console.log(data)
        });

});