简体   繁体   中英

How to cache the $http response for reuse in angularjs

I am trying to use $http.get() response as a service providing to controllers. Please help!

erp.service('elementData',['$http', '$cacheFactory', function($http, $cacheFactory){
    var fetchCache = $cacheFactory('ele', {number: 1}); 

    $http({url: "./php/fetchElement.php", 
    method: 'GET'}).success(function(data){
        fetchCache.put(1, data.records);
        console.log(fetchCache.info('ele'));        
        //return fetchCache.get(1);
    });
    console.log(fetchCache.info('ele'));



}])

console.log(fetchCache.info('ele')); provide different result.

To effectively cache the response from an HTTP call, and return that if present, I'd do something like this

angular.module('app').factory('dataService', dataService);
dataService.$inject = ['$http', '$q'];

function dataService($http, $q) {
    var service = {
        getGroups: getGroups,
        _groupCache: null
    };

    return service;

    function getGroups() {
        // Return from local cache variable if we have it.
        if (service._groupCache) return $q.resolve(service._groupCache);
        // Otherwise, return from API.
        return $http.get("api/ms/groups/").then(
            function (response) {
                service._groupCache = response.data;
                return response.data;
            }
        );
    }

This can then be injected into your controller and used like follows:

angular.module('app').controller('PageCtrl', PageCtrl);

PageCtrl.$inject = ['dataService'];

function PageCtrl(dataService) {
    var vm = this;
    // "Public" properties
    vm.groups = null;
    dataService.getGroups().then(function (groups) {
        vm.groups = groups;
    });
}

You should then have access to groups inside your page. The first time this code runs, _groupCache on the service will be null, so it will send the HTTP request. On subsequent runs, _groupCache will be populated. You could further refine this by storing the cached groups in local storage on the browser, which would keep it cached even after page loads.

Note that the return of the getGroups function will ALWAYS be asynchronous, so anything that needs that data should be chained onto a .then on the return of getGroups as in this example.

In your example, the .success callback will be executed asynchronously, therefore the second console.log will execute before the first. To fix just that problem, you'd re-write as this:

erp.service('elementData',['$http', '$cacheFactory', function($http, $cacheFactory){
    var fetchCache = $cacheFactory('ele', {number: 1}); 

    $http({url: "./php/fetchElement.php", 
    method: 'GET'}).then(function(data){
        fetchCache.put(1, data.records);
        console.log(fetchCache.info('ele'));        
    }).then(function () {
        console.log(fetchCache.info('ele'));
    });
}])

you can use a service variable.

erp.service('elementData',['$http', '$cacheFactory', function($http, $cacheFactory){
    var resource = {};
    // var fetchCache = $cacheFactory('ele', {number: 1}); 
    resource.loadedData = null;
    resource.getData = function(callback){  
      $http({url: "./php/fetchElement.php", 
      method: 'GET'}).succes(function(data){
        callback(data);
      });        
          //return fetchCache.get(1);
    }
    console.log(fetchCache.info('ele'));

}]);


/*....
In side of your controller */ 
  if(elementData.loadedData){
    $scope.elementData = elementData.loadedData;
    process();
  } else {
    elementData.getData(function(data){
      $scope.elementData = data;
      elementData.loadedData = data;
      /*
        if you want set it on localStorage you can use as
        localStorage.loadedData instead of elementData.loadedData;
      */
      process();
    });
  }
  function process(){
    /* then you can use your data*/
  }
//....

Thanks for all your help. I also found this:

erp.run(['$http', '$rootScope',
    function($http, $rootScope) {      
     $http({ cache: true, url: './php/fetchElement.php', method: 'GET'})
        .success(function(data) {
          $rootScope.resource = data.records;         
        });
    }
]);

erp.service('elementData',['$rootScope',
   function($rootScope) {
        //console.log($rootScope.resource);
        if($rootScope.resource){
            return $rootScope.resource;
        }
    }
]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM