简体   繁体   中英

AngularJS sharing data form AJAX $http request

I have the following controllers:

angular.module('app').controller('ParentCtrl', function(Service) {

   var list = []
   var init = function () {
      Service.query().success(function() {
          list = Service.getList();  
      });
   }
});

angular.module('app').controller('ChildCtrl', function(Service) {

   var list = []
   var init = function () {
      list = Service.getList();
   }
});

angular.module('app').factory('Service', function($http) {

     list = []
     return {
         query : function() {
             $http.get('/path/to/my/api').success(function(data){
                list = data
             })
         },
         getList: function() {
             return list;
         }
     }
  });

My HTML is as follows:

<div ng-controller="ParentCtrl as parent">
    <div ng-controller="ChildCtrl as child">

    </div>
</div>

So basically when I receive the AJAX request I want both the controllers to get updated with the data

The best way would be to return the promise from $http.get :

angular.module('app').factory('Service', function($http) {
   var promise;
   return {
     getList: function() {
         if (promise) {
             return promise;
         }

         promise = $http.get('/path/to/my/api');
         return promise;
     }
   }
});

angular.module('app').controller('ParentCtrl', function(Service) {    
   var list = [];
   var init = function () {
      Service.getList().then(function(response) {
          list = response.data;  
      });
   }
});

angular.module('app').controller('ChildCtrl', function(Service) {
   var list = [];
   var init = function () {
      Service.getList().then(function(response) {
          list = response.data;  
      });
   }
});

You can broadcast custom message to rootScope and Your controllers will get this message and handle it.

angular.module('app').controller('ParentCtrl', function($rootScope, $scope, Service) {

   $scope.list = [];

   $scope.$on('Service:list', function(event, data){
       $scope.list = data;
   });
});

angular.module('app').controller('ChildCtrl', function($rootScope, $scope, Service) {

   $scope.list = [];

   $scope.$on('Service:list', function(event, data){
       $scope.list = data;
   });

   Service.query(); // run once, get in both controllers
});

angular.module('app').factory('Service', function($rootScope, $http) {
     var list;

     return {
         query : function() {
             $http.get('/path/to/my/api').success(function(data){
                list = data;
                $rootScope.$broadcast('Service:list', list);
             })
         },
         getList: function() {
             return list;
         }
     }
});

You could handle it in many ways. One simple way is to cache the promise and return it.

Example:-

angular.module('app').factory('Service', function($http, $q) {
     var listPromise;
     return {
         getList: function() {
             //If promise is already present then 
             return listPromise || (listPromise = $http.get('/path/to/my/api').then(function(response){
                return response.data;
             })
             //Use the below 2 blocks (catch and finally) only if you need.
             //Invalidate in case of error
             .catch(function(error){ 
                  listPromise = null;
                  return $q.reject(error);
             })
            //Use finally to clean up promise only if you only need to avoid simultaneous request to the server and do not want to cache the data for ever.
            .finally(function(){ 
                listPromise = null;
             }));
         }
     }
  });

and in controller:

angular.module('app').controller('ParentCtrl', function(Service) {
   var list = [];
   var init = function () {
      Service.getList().then(function(data) {
          list = data;  
      });
   }
});

angular.module('app').controller('ChildCtrl', function(Service) {

   var list = [];
   var init = function () {
      Service.getList().then(function(data) {
          list = data;  
      });
   }
});

Caching a promise will make sure that it really does not matter who makes the first call and you always make the same service call to get the data and service will manage data caching via promise and prevent any duplicate calls.

Another practice is to implement a one-way data flow using flux pattern . Where you create stores that maintains data and it will make ajax call via a dispatcher and emits event to the subscribers of change event. There is an angular library ( flux-angular ) that can be used as well to implement this pattern. This will really help synchronize data between multiple components regardless of whether they are parent/child or siblings and regardless of who makes the first call etc..

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