0

Below is the code for CardLoader, which I am using to get a json file containing information about the playing cards I want to use. However, after I create a CardLoader in my client code, and then call the getGameCards() function, I am receiving an empty map. I have run through the debugger and the issue lies with the loadCards method. Since this is completing asynchronously, pickGameCards() is executed before the loadCards function has completed. I am unsure about how I should handle this? What techniques are there for waiting until completion?

function CardLoader(){
    var cards = this.loadCards();
    this.gameCards = this.pickGameCards(cards);
}

CardLoader.prototype.pickGameCards = function(cards){
    var random;
    var gameCards = {};
    var length = cards.length - 1;
    for(var i = length; i > length - 7; i--){
        gameCards[cards[i].name] = cards.splice(i, 1);
    }
    for(var i = 0 ; i < 10; i++){
        random = Math.floor((Math.random() * cards.length));
        gameCards[cards[random].name] = cards.splice(random, 1);
    }
    return gameCards;
}

CardLoader.prototype.loadCards = function(){
    var allCards = [];
    $.getJSON("cards.json", function(data){
        $.each(data.cards, function(index, value){
            allCards[index] = data.cards[index];
        });
        return allCards;
    });
}

CardLoader.prototype.getGameCards = function(){
    return gameCards;
}
johnsoe
  • 664
  • 1
  • 5
  • 13
  • 1
    Read up on callbacks - http://recurial.com/programming/understanding-callback-functions-in-javascript/ – Qantas 94 Heavy Nov 16 '13 at 23:26
  • 2
    See here http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call – elclanrs Nov 16 '13 at 23:27
  • possible duplicate of [How to return value from an asynchronous callback function?](http://stackoverflow.com/questions/6847697/how-to-return-value-from-an-asynchronous-callback-function) – Qantas 94 Heavy May 04 '14 at 07:19

1 Answers1

0

I suggest using promises instead of callbacks because promises change very little in your code when compared to synchronous whereas when using callbacks you need to rethink everything.

I had to change literally only 4 lines in your code.

function CardLoader(){
    var cards = this.loadCards();
    this.gameCards = this.pickGameCards(cards);
}

CardLoader.prototype.pickGameCards = function(cards) {
    return cards.then(function(cards) {
        var random;
        var gameCards = {};
        var length = cards.length - 1;
        for(var i = length; i > length - 7; i--){
            gameCards[cards[i].name] = cards.splice(i, 1);
        }
        for(var i = 0 ; i < 10; i++){
            random = Math.floor((Math.random() * cards.length));
            gameCards[cards[random].name] = cards.splice(random, 1);
        }
        return gameCards;
    });
}

CardLoader.prototype.loadCards = function(){
    return $.getJSON("cards.json").then(function(data){
        var allCards = [];
        $.each(data.cards, function(index, value){
            allCards[index] = data.cards[index];
        });
        return allCards;
    });
}

CardLoader.prototype.getGameCards = function() {
    return this.gameCards;
}

In client code:

$("#get-cards-button").click(function() {
     someCardLoader.getGameCards().then(function(cards) {

     });
});

Assumes at least jQuery 1.8, in earlier jQuery you need to use .pipe instead of .then

Esailija
  • 138,174
  • 23
  • 272
  • 326