jaemsnrg
jaemsnrg

Reputation: 47

Using promises to get ajax data

I have been trying to get the remainder of my code to wait for an ajax call to run before executing as I need info in an array first. I have tried multiple approaches, but I cannot figure out why they won't. It seems like using promises may be best practise in such a situation. Currently the ajax still runs after the .done and final console.log(3).

Please see code below:

$(document).ready(function(){
    var selectedChannels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var numberOfChannels = selectedChannels.length;
    var onlineChannels = [];
    var offlineChannels = [];

function getChannels(){

 for (var count = 0 ; count < numberOfChannels; count++) {

    $.ajax({
    url: "https://wind-bow.hyperdev.space/twitch-api/streams/"+ selectedChannels[count],
    type: "get",
    dataType: "jsonp",
    callback: "?",
      data: {
        }, 
        success: function(data) {
            if (data.stream) {
              var logo = data.stream.channel.logo
              var twitchName = data.stream.channel.display_name
              var details = data.stream.channel.status
              var link = data.stream.channel.url
              onlineChannels.push(twitchName);
              console.log(onlineChannels);
              console.log(1);

              $(".display-area").append("<div class=\"result-box online\"><img src="+ logo +" alt=\"twitchName\" class=\"profile-img\"></img><div class=\"title\">"+ twitchName +"</div><div class=\"description\">"+ details +"</div>");

            } 
        },
    }).done(function(){

    });
 }

 }

/* should run after ajax and onlineChannels array has been populated */
 function completeAjax() {
  var promised = getChannels();
  var promisedComplete = $.when(promised);
  promisedComplete.done(function(){
    console.log(onlineChannels);
    console.log(2);
  });
}

completeAjax();

console.log(3)
});

Upvotes: 1

Views: 67

Answers (2)

trincot
trincot

Reputation: 350127

You could use your counter to count down back to zero to see how many Ajax calls still need to finish:

for (var count = 0 ; count < numberOfChannels; count++) {
    $.ajax({
        // ...
        success: function(data) {
            count--; // <!--------- decrease count
            // ...
        },
    }).done(function(){
        if (!count) { // <!--------- see if this was the last one finishing.
            // All Ajax done.
            // ...following tasks are initiated here.
            //
        }
    });
}

To understand how this works it is important to realise that the success and done callbacks are not called before your loop has finished, and count has reached the maximum. From then on count only decreases.

Upvotes: 1

adeneo
adeneo

Reputation: 318182

You can map the ajax calls, and return promises, and then use $.when.apply to check that all the ajax calls have completed

$(document).ready(function() {
    var selectedChannels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var onlineChannels   = [];
    var offlineChannels  = [];

    function getChannels() {
        return $.map(selectedChannels, function(channel, index) {
            return $.ajax({
                url      : "https://wind-bow.hyperdev.space/twitch-api/streams/" + channel,
                type     : "GET",
                dataType : "jsonp",
                callback : "?",
                data     : {}
            }).done(function(data) {
                if (data.stream) {
                    var logo       = data.stream.channel.logo;
                    var twitchName = data.stream.channel.display_name;
                    var details    = data.stream.channel.status;
                    var link       = data.stream.channel.url;

                    onlineChannels.push(twitchName);

                    $(".display-area").append("<div class=\"result-box online\"><img src=" + logo + " alt=\"twitchName\" class=\"profile-img\"></img><div class=\"title\">" + twitchName + "</div><div class=\"description\">" + details + "</div>");
                }
            });
        });
    }

    $.when.apply($, getChannels()).done(function() {
        // all done, onlineChannels populated
    });

});

Upvotes: 3

Related Questions