I'm trying to make a method that returns an array of objects after getting the objects from an API. The problem is that the return from the factory happens before all the calls are finished. I've tried to use $q.defer but it still sends the return before it's ready to ship. This is what I've come up with so far.
angular.module('watchList').factory('storageService', ['$http', '$q', function ($http, $q) {
storage = {};
storage.getMovies = function () {
var movies = localStorage.getItem('movies');
var movieArray = angular.fromJson(movies);
var newArray = [];
var defer = $q.defer();
angular.forEach(movieArray, function (id) {
newArray.push($http.get(api + id));
});
$q.all(newArray).then(function (response) {
defer.resolve(response);
});
return defer.promise;
}
This is the controller that I'm trying to make the call from
angular.module('watchList').controller('watchListController', ['$scope', 'storageService', function ($scope, storageService) {
$scope.movies = storageService.getMovies();
I want the loop to finish everything before it returns the array.
You don't need to create a promise, you can just return the promise returned by the $q.all(newArray)
call.
The thing is that you cannot expect to get a result synchronously when it only becomes available asynchronously. So you need to keep with using then
:
storage.getMovies = function () {
var movies = localStorage.getItem('movies');
var movieArray = angular.fromJson(movies);
var newArray = movieArray.map(function (id) {
return $http.get(api + id);
});
return $q.all(newArray);
}
storageService.getMovies().then(function(movies) {
$scope.movies = movies;
// ... other code working with $scope.movies
});
Side note: the map
method does what you do with forEach
, but immediately returns the array, which is quite practical.