Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 709
Franquis Avatar asked Mar 26 '13 22:03

Franquis


2 Answers

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 */ });
like image 104
Dmitry Evseev Avatar answered Nov 03 '22 22:11

Dmitry Evseev


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.

like image 44
Roamer-1888 Avatar answered Nov 03 '22 23:11

Roamer-1888