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
}
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:
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 };
}
}]);