1

Look at this Codepen: http://codepen.io/anon/pen/mPeqBQ

var streamers = ["WagamamaTV", "losty123", "BlackDotATV", "Dendi", "VITALIC_DOTA2", "Singsing", "zonixxcs", "Attackerdota", "purgegamers", "Mikerina","ESL_LOL","jcarverpoker", "gnumme"];

The code query looks as follows:

$.each(streamers, function(key, value) {
    $.getJSON('https://api.twitch.tv/kraken/streams/' + value, function(channel) {
      if (channel["stream"] == null) {
        // ADD TABLE ROW WITH DATA (for details see codepen
      } else {
        // ADD TABLE ROW WITH DATA (for details see codepen)
      }
    });
});

The Order in which the table rows are added is more or less random. Can I influence this order somehow so that it preserves the original order given in the array "streamers"? Just go to the codepen and refresh it a few times, you'll see what I mean.

Thanks

3
  • 2
    Related, but maybe not a good enough dupe: stackoverflow.com/questions/35023574/… Commented Mar 4, 2016 at 21:41
  • Yes, use when done like @KevinB suggested. getJSON is asynchronous. What's happening in your case is that you create a bunch of ajax requests in a loop, but they don't wait on each other, and they don't finish in the same order they were created. That's why you see this randomness. Commented Mar 4, 2016 at 21:48
  • I think if you replaced $.when(dothis,dothat) with $.getJSON() in my answer it would solve this problem. Initially when i revoked my binding dupe vote I did it because i wasn't sure at the time if it was in fact doing the same thing. Commented Mar 4, 2016 at 21:50

2 Answers 2

3

This is because your AJAX calls are all running at the same time! They may not finish in the same order. One may be a bit faster or slower, so the order isn't the same.

To fix this, you can use promises. Basically, wait until all requests are done, then display the results in the same order.

P.S. You can use channel.stream instead of channel["stream"].

// Array shortened for example
var streamers = ["WagamamaTV", "losty123", "BlackDotATV", "Dendi"],
    promises = [];

$.each(streamers, function(key, value){
    // Push the promise into the array
    // We'll take care of the callback and building the table later
    promises.push($.getJSON('https://api.twitch.tv/kraken/streams/' + value));
});

// Now wait until *all* of the requests are done
$.when.apply($, promises).then(function(){
    // This function is passed one argument for each AJAX call,
    // they are passed in order.  So, we can loop over `arguments`
    // to get them in order
    $.each(arguments, function(key, val){
        // Each parameter is actually an array, it's what is normally returned
        // from an AJAX call: `[ data, statusText, jqXHR ]`
        var channel = val[0],
            value = streamers[key];

        if (channel.stream == null) {
            // ADD TABLE ROW WITH DATA (for details see codepen)
        } else {
            // ADD TABLE ROW WITH DATA (for details see codepen)
        }
    });
});

Updated codepen: http://codepen.io/anon/pen/GZpyXZ

Docs for $.when (See "Examples"): http://api.jquery.com/jQuery.when/

Sign up to request clarification or add additional context in comments.

1 Comment

Incredible! Thank you for your answer! Very much appreciated!
1

A different approach is to pre built the table in the desidered order with each line hidden and as soon as a response arrive do the work.

In this way you will reduce the success part of your getJSON to only the minimum work required to render the full lines.

$(function () {
  var streamers = ["WagamamaTV",
                   "losty123",
                   "BlackDotATV",
                   "Dendi",
                   "VITALIC_DOTA2",
                   "Singsing",
                   "zonixxcs",
                   "Attackerdota",
                   "purgegamers",
                   "Mikerina",
                   "ESL_LOL",
                   "jcarverpoker",
                   "gnumme"];

  // build before the full table....
  var cachedEle = $(".streamertable");
  $.each(streamers, function(key, value) {
    cachedEle.append("<tr style='display: none;'><td class='td-stream'>" + value + "</td><td class='td-stream' id='onoff" + value + "'>OFFLINE</td><td class='td-stream' id='viewers" + value + "'>-</td><td class='td-stream' id='game" + value + "'>-</td><td class='td-stream'><a href='http://twitch.tv/" + value + "'>KLICK</a></td></tr>");
  });

  // for each getJSON do only table updating
  $.each(streamers, function(key, value) {
    $.getJSON('https://api.twitch.tv/kraken/streams/' + value, function(channel) {
      if (channel["stream"] == null) {
        $('#onoff' + value).text('OFFLINE').css("color", "red");
      } else {
        $('#viewers' + value).text(channel.stream.viewers);
        $('#game' + value).text(channel.stream.game);
        $('#onoff' + value).text('ONLINE').css("color", "blue");
      }
      $("#onoff" + value).parent('tr').show();
    });
  });
  $(".islive").html("Streams checked!");
});
.streamertable {
  margin: 10px;
  min-width: 700px;
}

.td-stream {
  padding: 5px
}
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>

<div class="container">
    <span class="islive">Checking Stream Status...</span>
</div>


<table class="streamertable" border="0">
    <tr>
        <td class="td-stream" style="font-weight: bold">Name</td>
        <td class="td-stream" style="font-weight: bold">Online</td>
        <td class="td-stream" style="font-weight: bold">Viewers</td>
        <td class="td-stream" style="font-weight: bold">Game</td>
        <td class="td-stream" style="font-weight: bold">Link</td>
    </tr>
</table>

1 Comment

Thanks a lot mate! Really appreciate, you put so much work in this answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.