Franquis
Franquis

Reputation: 743

Chaining an unknown number of promises in AngularJS

OK, let's say I have an array of n XHR requests:

var promises = [];
var AllResults = [];
$scope.requests = [
    {
        "uri":"http://foo/bar/action1",
        "name":"Action1"
    },{
        "uri":"http://bar/foo/action2",
        "name":"Action2"
    },{...},{...},{...}
];
var ParseMyResultsArray = function(){
    console.log(AllResults);
    //...
};

angular.forEach($scope.requests, function(request){
    var promise = $http.get(request.uri);
    promises.push(promise);
});

angular.forEach(promises, function(promise){
    promise.then(function(results){
        AllResults.push(results);
    });
});

//Then, when all promise are resolved...
ParseMyResultsArray();

How can I be sure to call ParseMyResultsArray() when all the promises are resolved without knowing the size of my requests array?

Thanks for your help!

Upvotes: 8

Views: 6925

Answers (2)

Roamer-1888
Roamer-1888

Reputation: 19288

I know this question is over a year old but it deserves a better answer.

The code can be far more concise and the ugly outer vars promises and AllResults and outer function ParseMyResultsArray() can be avoided.

Try ...

$scope.requests = [{
        "uri":"http://foo/bar/action1",
        "name":"Action1"
    }, {
        "uri":"http://bar/foo/action2",
        "name":"Action2"
    },{...},{...},{...
}];

$q.all($scope.requests.map(function(request) {
    return $http.get(request.uri);
})).then(function(results) {
    console.log(results);
    //parse results array here ...
    return parsedResults;
});

If further access to parsedResults is required, then by all means keep (or return) a reference to the promise returned by $q.all(...).then(...). Due to the asynchronicity involved in obtaining the data, this promise of parsedResults will be far more useful than the raw outer var AllResults.

Upvotes: 8

Dmytro Evseev
Dmytro Evseev

Reputation: 11581

From angular docs to $http:

The $http API is based on the deferred/promise APIs exposed by the $q service.

Hence it is possible to use $q.all() method that takes an array of promises and:

combines multiple promises into a single promise that is resolved when all of the input promises are resolved

The implementation code is:

$q.all(promises).then(function () { /* All promises are resolved */ });

Upvotes: 17

Related Questions