Unable to access data from service

I have a requirement where I want to retrieve a JSON object from the server. Below are two versions which do not work -

Version 1

app.service("authorization", ['$http', function($http){
  var authMap = [];
  $http.get('/authmap').success(function(data){this.authMap = data});
}]);

Version 2

app.service("authorization", ['$http', function($http){
  var authMap = [];
  $http.get('/authmap').success(function(data){authMap = data});

  var getAuthMap = function(){return authMap};
}]);

In version one I am injecting the service into my controller and accessing it as authorization.authMap, it returns an empty [].

In version two, I am accessing it as authorization.getAuthMap(). Here it gives me an error that no such method is defined on the object ?

What is wrong with both the methods ?

Just make the variables part of that services scope

app.service("authorization", ['$http', function($http){
    var authorizationScope = this;
    authorizationScope.authMap = [];
    $http.get('/authmap').success(function(data){authorizationScope .authMap = data});
}]);

Version 2

app.service("authorization", ['$http', function($http){
    var authorizationScope = this;
    authorizationScope.authMap = [];
    $http.get('/authmap').success(function(data){authorizationScope.authMap = data});

    authorizationScope.getAuthMap = function(){return authorizationScope.authMap};
}]);

That way in your controller when you inject it you can access that variable or function

function myController($scope, authorization){
    authorization.authMap //this is how you would access the variable here
    authorization.getAuthMap(); //this is how you would access the function
}

  1. You should expose your function.
  2. You need to understand that $http is an asynchronuous call. Easiest way to fix is to return the $http promise to your controller and resolve the data there.

So:

app.service("authorization", ['$http', function($http){
  return {
     getAuthMap : function(){
        return $http.get('/authmap');
     }
  };
}]);

In your controller:

authorization.getAuthMap().then(function(data) {
    $scope.data = data;
});

If the data is complex and should be processed within your service, you could use service $q in your service and return its promise to your controller. This makes the service slightly more complex:

app.service("authorization", ['$http', '$q', function($http, $q) {

  var authMap;

  return {
     getAuthMap : function(){
        var deferred = $q.defer();
        var promise = deferred.promise;

        promise.then(function() {
           if (!authMap) {
              $http.get('/authmap').success(function(data) {
                 var changedData = data;
                 // do sth with data
                 authMap = changedData;

                 deferred.resolve(changedData);
              });
           } else {
              deferred.resolve(authMap)
           }
        });
        return deferred.promise;
     }
  };
}]);

You already asked about version 1 in another post, and it was answered there: Unable to set a class var in $http callback

To summarize: the success() and error() methods are called with the function context (i.e., this) set to the global context (i.e., window). So this.authMap = data stores the data in window.authMap, rather than in your service. You need to create a closure (by defining a local variable and setting it to this) and then use that variable in the success() function:

app.service("authorization", ['$http', function($http){
  this.authMap = [];
  var self = this;
  $http.get('/authmap')
     .success(function(data){
        self.authMap = data
     })
     .error(function(data, status){
        alert('Unable to authorize')
        console.log(status)
     })
}]);

Version 2 has two problems:

  1. Same problem as version 1
  2. You are using service(), so the body of the service function needs to be a JavaScript constructor function (because Angular will instantiate the service by essentially calling new on the constructor function). So, public properties (including functions/methods) need to be defined on this:
app.service("authorization", ['$http', function($http){
   this.authMap = [];
   this.getAuthMap = function(){ return this.authMap };
   var self = this;
   $http.get('/authmap')
      .success(function(data){
         self.getAuthMap = data
      })
      .error(function(data, status){
         alert('Unable to authorize')
         console.log(status)
      })
}]);

If you want to keep authMap private, use a factory() instead:

app.factory("authorization", ['$http', function($http){
   var authMap = [];         // private data
   $http.get('/authmap')
      .success(function(data){
         authMap = data
      })
      .error(function(data, status){
         alert('Unable to authorize')
         console.log(status)
      })
   return {
      getAuthMap: function() { return authMap };
   }
}]);