Kyle
Kyle

Reputation: 58

Wait for loop to finish $.getJSON for each array item before outputting data

I've got an array of names which I need to retrieve data from, and I'm currently doing this with $.getJSON inside a loop. It works and I can retrieve the data, but to output the correct value I need to use setTimeout or similar. I'm wondering if there's a more refined way of doing what I'm looking to achieve.

Here's what I've got.

var names = ["riotgames", "example"];
var online = [];

for (var i = 0; i < names.length; i++) {
  $.getJSON('https://api.twitch.tv/kraken/streams/' + names[i], function(data) {
    if (data.stream != null) {
      online.push(data.stream.channel.display_name);
    };
  });
}

console.log(online) // outputs []

setTimeout(function() {
  console.log(online) // outputs correctly
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Upvotes: 1

Views: 1652

Answers (1)

gen_Eric
gen_Eric

Reputation: 227220

When doing $.getJSON, you are triggering asynchronous requests. This means they run in the background. You do not wait for them to finish, their callbacks will trigger (like an event) once the request is done.

This means you cannot access online from outside the callback(s).

If you want to "wait" for all the requests to finish, then I suggest using promises. You can use $.when to combine all the requests into one promise then run a callback once everything is done.

var names = ["riotgames", "example"];
var promises = [];

for (var i = 0; i < names.length; i++) {
    // $.getJSON returns a promise
    promises.push($.getJSON('https://api.twitch.tv/kraken/streams/' + names[i]));
}

// Combine all promises
// and run a callback
$.when.apply($, promises).then(function(){
    var online = [];

    // This callback will be passed the result of each AJAX call as a parameter
    for(var i = 0; i < arguments.length; i++){
        // arguments[i][0] is needed because each argument
        // is an array of 3 elements.
        // The data, the status, and the jqXHR object
        online.push(arguments[i][0].stream.channel.display_name);
    }

    console.log(online);
});

Upvotes: 4

Related Questions