Dom
Dom

Reputation: 734

jQuery JSON queries - order is random

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

Upvotes: 1

Views: 69

Answers (2)

gaetanoM
gaetanoM

Reputation: 42054

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>

Upvotes: 1

gen_Eric
gen_Eric

Reputation: 227310

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/

Upvotes: 3

Related Questions