0

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.

Knikedix
  • 15
  • 1
  • 3
  • Take a look here. It will help you http://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed – Steeve Pitis Mar 03 '17 at 18:03
  • Put your return in a function and call that from your api success callback. this way you won't return anything until the api call is completed. – PersyJack Mar 03 '17 at 18:14

2 Answers2

0

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.

trincot
  • 317,000
  • 35
  • 244
  • 286
-1

getMovies will return immediately with a promise. You need to use "then" to wait on that promise.

$scope.movies = storageService.getMovies().then((response) => ...)
PeteH
  • 79
  • 6