Search code examples
angularjsangular-servicesangularjs-rootscope

$rootScope property value undefined in service


I have a table in a database that i need to access before anything else goes on in my website. The values that i get, i'll be using all throughout different controllers, directives, services etc. I thought the best place to store those values would be in the $rootScope so to that end, i did the following:

obApp.run(function($rootScope, ngProgress, $timeout) {
  $.post('phpProcessingPage', function(data){
   $rootScope.domains = JSON.parse(data); //this "domains" property is what i'm interested in
  })
})

I get the domains back without a hitch so all is good. The problem is, when i inject the $rootScope into a service:

obApp.factory('requestOrigin', ['$rootScope', function($rootScope){
   console.log($rootScope.domains); //this is undefined at this point
   return $rootScope.domains; //returns undefined
}]);

It's to be expected that there would be nothing there as the response would come after the service code executed.

The problem is, i use that factory code in multiple controllers and i don't know how to delay it's execution so that it waits until i get data back from my ajax call.

I've tried doing a broadcast but there's no way (that i know of) to delay the retun of the factory even if at some point i do get the results back. How would i go about this problem that i have?

ANSWER:

Scrap the usage of $rootScope for this. The controller where i use the returned results from the service looks like this:

oApp.controller(['serviceName', function(serviceName){
    serviceName.then(function(response){
      //here i have the data from the ajax call, the service made
      //other things to do
    });
}]);

And the service looks like this:

obApp.factory(['serviceName','$http', function(serviceName, $http){
    return $http.post('phpProcessingPage.php', {cache: true});
}]);

Solution

  • I'd say you need to redesign this little thing using promises.

    Use a service to store and return this data, and from your controllers/directive/etc, you can do the following:

    DomainService.getDomains().then(function () {
        // Do whatever you need, here you'll have the data
    });
    

    Now the service should return the data, or fetch it from the server when it doesn't have it when the app is running for the first time:

    // Domain service
    var domains;
    
    var getDomains = function () {
        // using angular's $q service
        var deferred = $q.defer();
    
        if (domains) {
            // returns the data without going to the server
            deferred.resolve(domains);
        }  
        else {
            // fetches the data the first time, also notice angular's $http service
            $http.post('phpProcessingPage', data).then(function(response)
                domains = response;
                deferred.resolve(domains);
            });
        }
    
        return deferred.promise;
    }