According to AngularJS, my $http
call through a service from my controller is returning undefined?
What seems to be the issue here? I am trying to return the data called, but once passed to the controller the data bees undefined?
JavaScript
var myStore = angular.module('myStore', [])
.controller('StoreController', ['$scope', 'dataService', function ($scope, dataService) {
$scope.products = dataService.getData();
}])
.service('dataService', ['$http', function($http) {
this.getData = function() {
$http.get('assets/scripts/data/products.json')
.then(function(data) {
return data;
});
};
}]);
HTML
<div class="content">
<ul>
<li ng-repeat="product in products.products">{{product.productName}}</li>
</ul>
</div>
I understand that $http
, $q
, and $resource
all return promises, but I thought I had covered that with .then.
According to AngularJS, my $http
call through a service from my controller is returning undefined?
What seems to be the issue here? I am trying to return the data called, but once passed to the controller the data bees undefined?
JavaScript
var myStore = angular.module('myStore', [])
.controller('StoreController', ['$scope', 'dataService', function ($scope, dataService) {
$scope.products = dataService.getData();
}])
.service('dataService', ['$http', function($http) {
this.getData = function() {
$http.get('assets/scripts/data/products.json')
.then(function(data) {
return data;
});
};
}]);
HTML
<div class="content">
<ul>
<li ng-repeat="product in products.products">{{product.productName}}</li>
</ul>
</div>
I understand that $http
, $q
, and $resource
all return promises, but I thought I had covered that with .then.
-
2
getData()
doesn't have areturn
statement of its own. Thereturn data
instead applies only to the callback,function(data)
. Though,$http
is also asynchronous, meaninggetData()
doesn't wait fordata
to bee available -- How to return the response from an asynchronous call? Note especially the mentions of Promises (.then()
-ables). – Jonathan Lonowski Commented Apr 20, 2015 at 3:09 -
Just add
return this
as the last line of the service, hope it will solve your problem – Ali Adravi Commented Oct 19, 2015 at 20:35
2 Answers
Reset to default 5The problem could be that you are not return
ing the promise created by $http.get
in your dataService.getData
function. In other words, you may solve your undefined
issue by changing what you have to this:
.service('dataService', ['$http', function($http) {
this.getData = function() {
return $http.get...
};
}
If you had multiple calls to $http.get
within dataService.getData
, here is how you might handle them.
.service('dataService', ['$http', function($http) {
this.getData = function() {
var binedData, promise;
binedData = {};
promise = $http.get(<resource1>);
promise.then(function (data1) {
binedData['resource1Response'] = data1;
return $http.get(<resource2>);
});
return promise.then(function (data2) {
binedData['resource2Response'] = data2;
return binedData;
});
};
}]);
A much cleaner way, however, would be to use $q.all
.service('dataService', ['$http', '$q', function($http, $q) {
this.getData = function() {
var binedData, promises;
binedData = {};
promises = $q.all([
$http.get(<resource1>),
$http.get(<resource2>)
]);
return promises.then(function (allData) {
console.log('resource1 response', allData[0]);
console.log('resource2 response', allData[1]);
return allData;
});
};
}]);
You're problem does lie in the fact that you are not returning a promise but as you stated in @maxenglander's post you may have multiple http calls involved which means you should start creating and resolving your own promise using $q:
.service('dataService', ['$http', '$q', function($http, $q) {
return $http.get('assets/scripts/data/products.json')
.then(function(data) {
//possibly do work on data
return <<mutated data>>;
});
}];
or if you have multiple http calls and need to do some bination work you can do something $q.all:
.service('dataService', ['$http', '$q', function($http, $q) {
var p1 = $http.get('assets/scripts/data/products.json');
var p2 = $http.get('assets/scripts/data/products2.json');
return $q.all([p1, p2]).then(function(result){
//do some logic with p1 and p2's result
return <<p1&p2s result>>;
});
}];
then in your controller you will need to do:
.controller('StoreController', ['$scope', 'dataService', function ($scope, dataService) {
dataService.getData().then(function(result){
$scope.products = result;
});
}]);
What this allows in your service is now you can do plex calls like say call two webservices inside and wait till they are both plete then resolve the promise. What I'm trying to express here is that you don't need to return the promise provided by the $http.get function, but since you are doing an async action you DO need to return some promise that will be later fulfilled and acted on.