greenfox
greenfox

Reputation: 198

loop of promises after a single promise

I just have to write a promise, then, with the result of this promise, an array of movies, I have to loop inside the array and for each element do a remote call (with promise too) to decorate with additional data. I tried this way:

var deferred = $q.defer();
var promises = [];

angular.forEach(tree, function(node) {
    promises.push(
        APICall.GetMovieList(node).then(function(success){
            var contents = {};
            //simple data manipulation
            return contents;
        })
        .then(function(contents){ /////////////////////// concatenation part that won't work
            angular.forEach(contents, function(content) {
                APICall.GetMovieDetails(content.ID).then(function(success){
                    content.metadata = success.metadata;    
                });
            });
            return contents;
        })
    );
});


$q.all(promises).then(ResolveFunction);

return deferred.promise;

For the sake of readability I deleted the ResolveFunction, it simply manage the promise array and do a $q.resolve(results). The thing is that without the concatenation it works like a charm, but with the necessary concatenation it does just return the same result as before, it behave like this due to async calls that will be called after... Is it a good idea to create another deferred and nest a $q.all inside the concatenation part and return the $q.all solved array promise? Thanks so much

Upvotes: 0

Views: 644

Answers (1)

friedi
friedi

Reputation: 4360

You don't need to create a second deferred (you don't need a deferred at all).
Simply do the following:

var promises = [];

angular.forEach(tree, function(node) {
    promises.push(
        APICall.GetMovieList(node).then(function(success){
            var contents = {};
            //simple data manipulation
            return contents;
        })
        .then(function(contents){ 
            var contentPromises = [];
            angular.forEach(contents, function(content) {
                contentPromises.push(
                    APICall.GetMovieDetails(content.ID).then(function(success){
                        content.metadata = success.metadata;    
                    })
                );
            });
            return $q.all(contentPromises).then(function() {
                return contents;
            });
        })
    );
});

return $q.all(promises).then(function(nodes) {
    return nodes;
});

Here is a working jsfiddle-demo with a mocked APICall-Factory.

Upvotes: 1

Related Questions