Faisal
Faisal

Reputation: 878

How to post inside a loop with AngularJS 1.4.8

I have found other answers to similar questions of mine, but none of them worked for me.

I'm trying to create a cards game. Here I'm trying to shuffle through the cards and give each player 5 random Money cards ( $scope.MoneyCards ). Instead, this code gives all the 15 cards to the last player on the loop.

The results with ( Angular 1.0.8 ) is exactly how I want it. But when I'm using any later version this doesn't work. I'm working on migrating to 1.4.8 .

This is the code I'm using:

    $scope.StartGame = function() {
    $http.get('/api/MoneyCards')
        .success(function(data) {
            $scope.MoneyCards = data;
            console.log(data);

            // Loop through players
            player = 1;
            while(player < 4) {
            // Loop through money cards to give each player 5 cards
            i=0;
            while(i < 5) {
                // Shuffle
                var Mfloor = Math.floor(Math.random()*$scope.MoneyCards.length);
                $scope.randomCard = $scope.MoneyCards.splice(Mfloor, 1 );
                // Create the card in the Deck table and attach it to a player
                $scope.createDecks($scope.randomCard[0],player,0);
                i++;
            }
            player++;
        }

        })
        .error(function(data) {
            console.log('Error: ' + data);
        });
};

This is the createDecks function

$scope.createDecks = function(card, player, type) {

    $scope.formData.player = player;
    $scope.formData.type = type;
    $scope.formData.card = card;

    $http.post('/api/Decks', $scope.formData)
        .success(function(data) {
            $scope.formData = {};
            console.log(data);
        })
        .error(function(data) {
            console.log('Error: ' + data);
        });
};

I'll try to adopt this to JSFiddle.

Code provided by georgeawg using $q and still not working

    $scope.StartGame = function() {
    $http.get('/api/MoneyCards')
        .success(function(data) {
            $scope.MoneyCards = data;
            console.log(data);

            var player = 0;
            while(player < 3){
            var i = 0;
            var qPromise = $q.when(0);
                while(i < 5) {
                    // Shuffle
                    var Mfloor = Math.floor(Math.random()*$scope.MoneyCards.length);
                    var randomCard = $scope.MoneyCards.splice(Mfloor, 1 );
                    // Create the card in the Deck table and attach it to a player

                    qPromise = qPromise.then( function (response) {
                        return $q.all([
                            response,
                            $scope.createDecksPromise(randomCard[0],player,0)
                            ]);
                        });
                    i++;
                };
                player += 1;
            };

            qPromise.then ( function(response) {
                      //do whatever
                    console.log(response);
                 }) .catch ( function (error) {
                      throw error;
                 });

        })
        .error(function(data) {
            console.log('Error: ' + data);
        });
};

Upvotes: 2

Views: 816

Answers (2)

georgeawg
georgeawg

Reputation: 48968

First yourcreateDecks function should return promises.

$scope.createDecksPromise = function(card, player, type) {

    var formData = {};
    formData.player = player;
    formData.type = type;
    formData.card = card;

    return $http.post('/api/Decks', formData);
};

Your iterative loop should then chain those promises.

var i = 0;
var qPromise = $q.when([]);
while(i < 5) {
    // Shuffle
    var Mfloor = Math.floor(Math.random()*$scope.MoneyCards.length);
    var randomCard = $scope.MoneyCards.splice(Mfloor, 1 );
    // Create the card in the Deck table and attach it to a player
    // Add closure for randomCard and player 
    (function (randomCard, player) {
        qPromise = qPromise.then( function (response) {
            response.push(
                $scope.createDecksPromise(randomCard[0],player,0)
            );
            return $q.all(response);  
        });
    })(randomCard, player); 
    i++;
};

qPromise.then ( function(response) {
          //do whatever
     }) .catch ( function (error) {
          throw error;
     });

Remember that when chaining promises you should always return something to the .then method.

Also be aware that the .then method has a different response structure than the .success method.

The AngularJS team has come to their senses and deprecated .success. We should all be using the .then method now. To learn more about the deprecation (or should I say failure) of .success and .error, see the latest AngularJS $http API Docs.

To learn more about $q.when, look at the AngularJS $q Service API Docs.

Upvotes: 3

Faisal
Faisal

Reputation: 878

I have finally found the answer, here is the code:

$scope.StartGame = function() {
    $http.get('/api/MoneyCards')
        .success(function(data) {
            $scope.MoneyCards = data;
            console.log(data);

            var qPromise = [];
            var player = 1;
            while(player < 4){
            var i = 0;
                while(i < 5) {

                    qPromise.push([
                        Mfloor = Math.floor(Math.random()*$scope.MoneyCards.length),
                        randomCard = $scope.MoneyCards.splice(Mfloor, 1 ),
                        $scope.createDecksPromise(randomCard[0],player,0)
                    ]);

                    i++;
                };
                player += 1;
            };
            return $q.all(qPromise);

        })
        .error(function(data) {
            console.log('Error: ' + data);
        });
};

Thanks to georgeawg, the $http.post $scope.createDeckPromise() should return promises:

$scope.createDecksPromise = function(card, player, type) {

    var formData = {};
    formData.player = player;
    formData.type = type;
    formData.card = card;

    return $http.post('/api/Decks', formData);
};

For whoever is having the same issue. This is the solution without my code:

$scope.RunCode(){
    var Promises = [];
    var i = 0;
    while (i < 5){
        Promises.push($http.post('/api/whatever', formData));
        // to add multiple functions to the promise use [], example: Promises.push([doThing1, doThing2]); 
        i++;
    };
    return $q.all(Promises);
}

Upvotes: 1

Related Questions