Cas Cornelissen Cas Cornelissen - 6 months ago 14
AngularJS Question

AngularJS nesting $http calls

I'm trying to write a factory that gets data from two sources and uses one source to expand the data in the other object.

app.factory('information', ['$http', '$q', 'players', 'matches', function($http, $q, players, matches) {
return {
// Returns all matches and players including extra parsing
get: function() {
return players.get().success(function(data) {
players = data;

matches.get().success(function(data) {
matches = data;

for ( match in matches ) {
matches[match].a_player1 = players.filter(function(player) { return player.username == matches[match].a_player1 })[0];
matches[match].a_player2 = players.filter(function(player) { return player.username == matches[match].a_player2 })[0];
matches[match].b_player1 = players.filter(function(player) { return player.username == matches[match].b_player1 })[0];
matches[match].b_player2 = players.filter(function(player) { return player.username == matches[match].b_player2 })[0];
console.log(matches)
}

return matches;
});
});
},
}
}]);


Both
matches.get()
and
players.get()
are simple
GET
requests to an API like so:

app.factory('players', function($http) {
return {
get: function() {
return $http({
method: 'GET',
url: '/players',
});
},
}
});


But the above code (of course) returns the
players
object while I want it to return the
matches
object after it gets combined with the
players
object.

Any tips on how to do this?

Answer

That function won't return anything since you can't directly return a value from an async operation, either return the promise or use a callback. But I think what you're looking for is $q.all:

return {
        // Returns all matches and players including extra parsing
        getEverything: function() {

        var getPlayers= $http({
            method: 'GET',
            url: '/players',
        });
        var getMatches= $http({
            method: 'GET',
            url: '/matches',
        });

           return $q.all([getPlayers,getMatches]);
        }
}

Usage:

getEverything().then(function(data){
   var players=data[0].data;
   var matches=data[1].data;
})

EDIT:

Irrelevant, but to move this back in the factory:

getEverything: function() {
            var getPlayers= $http({
                method: 'GET',
                url: '/players',
            });
            var getMatches= $http({
                method: 'GET',
                url: '/matches',
            });
            return $q.all([getPlayers,getMatches]);
},
getEverythingMapped:function(){
 var deferred = $q.defer();
 this.getEverything().then(function(data){
       var players=data[0].data;
       var matches=data[1].data;
//do as many loops on either result set as you like
                for ( match in matches ) {
                    matches[match].a_player1 = players.filter(function(player) { return   player.username == matches[match].a_player1 })[0];
                    matches[match].a_player2 = players.filter(function(player) { return player.username == matches[match].a_player2 })[0];
                    matches[match].b_player1 = players.filter(function(player) { return player.username == matches[match].b_player1 })[0];
                    matches[match].b_player2 = players.filter(function(player) { return player.username == matches[match].b_player2 })[0];
                    console.log(matches)
//use of a promise here allows us top use this method using -then, we need to so this since we're
//waiting for the result of an async server call before we can loop through players and matches
                     deferred.resolve(matches);
                }


 }
}

Now you would use the above method like this in your controller:

information.getEverythingMapped().then(function(matches){
 console.log(matches);
})
Comments