简体   繁体   中英

How can I simulate a $http success in angular?

I have a service that I use in several of the controllers in my app.

The service contains a $http call to a php script that returns some important data.

What I want to do is to get that data from the user's localstorage if the request fails, and then call all the functions bound to the $http success in all the controllers.

This is what a part of my service looks like:

app.service('initialJSON', ['$http', function ($http) {
  var vm = this;
  vm.json = $http.get(url);
  vm.json.success(function (data) {
    if (typeof Storage !== "undefined") {
      localStorage.initialJSON = data;
    }
  })
  vm.json.error(function (data, status) {
    if (typeof Storage !== "undefined" && "initialJSON" in localStorage) {
      // call all success functions in all controllers with the locally saved data
    }
  });
}]);

As an example the function in this controller should be called:

app.controller('someCtrl', ['initialJSON', function(initialJSON) {
  var vm = this;

  initialJSON.json.success(function (data) {
    // This function should be called and do some things with the data
  });

}]);

I don't know if this is possible or how much of my structure I would have to change to make it possible, but if someone has an idea I would really appreciate it.

Rather than have your controllers re-use the same $http promise, create your own that you will resolve with the results once you've obtained them.

app.service('initialJSON', ['$http', '$q', function ($http, $q) {
  var vm = this;
  var deferred = $q.defer();
  vm.json = deferred.promise;

  var request = $http.get(url);
  request.then(function (response) {
    if (typeof Storage !== "undefined") {
      localStorage.initialJSON = response.data;
      deferred.resolve(response.data);
    }
  })
  request.catch(function () {
    if (typeof Storage !== "undefined" && "initialJSON" in localStorage) {
        deferred.resolve(localStorage.initialJSON);
    }
  });
}]);

If your controllers only care about success the above should work. If you need them to be able to handle errors as well you'll need to extend it in some way to call deferred.reject() after making both attempts to get the data.

You can go with just local storage and cookies: https://github.com/grevory/angular-local-storage

Or if you're looking for something a little more architected: https://github.com/angular-pouchdb/angular-pouchdb

When you say "call all the success functions" you should really be wrapping these calls in a promise. So a service might look like:

service('myService', ['$q',function($q){
    var _privateServiceCall = function(){
         return myPromiseBasedCall().then(
             function(response){return response;}
         ).catch(function(err){
            throw(err);
         });
    };
    return {
        publicServiceCall = function(){
           var defer = $q.defer();
            _privateServiceCall().then(function(response){
                defer.resolve(response);
            }).catch(function(err){
                throw err;
            })
            return defer.promise;
        }
    }
}]);

When a controller needs data from the service it will request that data, and when it is ready those promises will be resolved.

.controller('myController', ['$scope', 'myService', function($scope, myService){
    myService.publicServiceCall().then(function(response){
        console.log(response);
    });
}
}]);

If you want to setup a broadcast whenever data is updated on some set schedule or the like you can use rootscope broadcasts in the service, and scope listeners in the controllers (scope inherits rootscope, but doesn't cause memory leaks like rootscope listeners do). However you should use the promises pattern whenever possible.

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