0

I am very new to programming, I am doing freecodecamp twitch tv JSON API project, I managed to get the names in different divs but everytime I refresh it has a different order (I want order to be same every time), I tried everything can someone please explain what I need to do???

  function twitchTV(){
    var twitchers = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var output = "";    
    for (var i = 0; i < twitchers.length; i++){
      var channelName = twitchers[i];
      var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/' + channelName + '/';      
      $.getJSON(apiQueryBio, function(json) {            
        output += '<div class="name">' + json["name"] + '</div>';
        $("#name").html(output);        
      });     
    }    
    }
  
  twitchTV();
  body {
    margin-top: 30px;
  } 
  
  .name {
    border: 2px solid black;
    margin: 5px;
    padding: 3px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="name"></div>
  <div id="bio"></div>
  <div id="stream"></div>
</div>

4
  • Have you attempted JS' '.forEach()' method? This will iterate over elements in ascending order Commented Mar 13, 2018 at 23:21
  • 2
    forEach() won't make any difference. The results come back in seemingly random order because $.getJSON makes asynchronous calls. Commented Mar 13, 2018 at 23:23
  • 1
    It's because of $.getJSON. This function does a network request which will take some time. Some may take 5ms, others can take 20. And they can switch depending on internet speed. It's like telling 20 people to go get information. While they're getting it, one can run into traffic, another can trip over a rock, and another can have a clear route and finish fast. So you'll have to get creative on how you want to handle the data once it comes back from the internet. Commented Mar 13, 2018 at 23:39
  • The new accepted answer is the worst approach because the requests are serialized, so you will provide a poor solution. Why did you undo the acceptance of my answer? Commented Mar 16, 2018 at 8:56

5 Answers 5

1

The function $.getJSON executes an async request, and the execution order isn't guaranteed.

You can use the function $.when to render the HTML after the whole set of request ends its job.

This way, the order is always the same because the function $.when waits for every registered ajax request (deferred object), and then with a simple for-loop, we can render the HTML according to the order of previous executions.

  • The function $.when() receives the deferred objects.
  • This approach uses the function apply to pass the deferred objects through an array.
  • The function done is called when every deferred object has done its job, so the callback will be called.

function twitchTV() {
  var twitchers = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
  var output = "";
  var requests = [];
  for (var i = 0; i < twitchers.length; i++) {
    var channelName = twitchers[i];
    var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/' + channelName + '/';
    requests.push($.getJSON(apiQueryBio));
  }

  $.when.apply(null, requests).done(function() {
    for (var json of arguments) {
      output += '<div class="name">' + json[0]["name"] + '</div>';
    }
    
    $("#name").html(output);
  });
}

twitchTV();
body {
  margin-top: 30px;
}

.name {
  border: 2px solid black;
  margin: 5px;
  padding: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="name"></div>
  <div id="bio"></div>
  <div id="stream"></div>
</div>

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

3 Comments

That's wonderful, can please explain to me little bit second part of the code what is happening there after you apply $.when.apply... what is .when, . apply, .done is doing why there is null argument. I really appreciate this. Thanks in advance.
@iffitheking explanation added, see the answer. Why did you undo the acceptance of this answer?
Your answer and explanation is absolutely correct, but whatever I was trying to achieve I could not get it done by your solution. So please take no offence in that.
0

ajax calls are asyncronous. there is no guarantee that it will finish in the order you send it out.

you have one of two options:

1) always wait until the previous request is complete before making the next request

2) add placeholders before the request is called

Option 1)

Benefit: Easy to setup/code

Con: you can't run multiple requests at once

example:

var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/';
var twitchers = [
  "ESL_SC2",
  "OgamingSC2",
  "cretetion",
  "freecodecamp",
  "storbeck",
  "habathcx",
  "RobotCaleb",
  "noobs2ninjas"
];
  
function twitchTV(twitchers){
  if(twitchers.length){
    $.getJSON(apiQueryBio + twitchers[0] + '/', function(json) {
      setName(json['name'])
      twitchTV(twitchers.slice(1,twitchers.length));
    });
  } 
}

function setName(name){
  $("#name").append('<div class="name">' + name + '</div>');
}
  
twitchTV(twitchers);
body {
    margin-top: 30px;
  } 
  
  .name {
    border: 2px solid black;
    margin: 5px;
    padding: 3px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="name"></div>
  <div id="bio"></div>
  <div id="stream"></div>
</div>

Option 2)

benefits: Multiple Parallel Calls cons: a little bit more html needed

  var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/';

function twitchTV(){
  var twitchers = [
    "ESL_SC2",
    "OgamingSC2",
    "cretetion",
    "freecodecamp",
    "storbeck",
    "habathcx",
    "RobotCaleb",
    "noobs2ninjas"
  ];
  for(var i = 0; i < twitchers.length; i++){
    var currentTwitch = twitchers[i];
    setPlaceholder(currentTwitch);
    setName(currentTwitch)
  }
   
}

function setName(twitcher){
  $.getJSON(apiQueryBio + twitcher + '/', function(json) {
    $('#' + twitcher).html(json['name']);
  });
}

function setPlaceholder(name){
  $("#name").append('<div class="name" id="' + name + '"><img src="http://gifimage.net/wp-content/uploads/2017/11/gif-of-3-dots-4.gif"/></div>');
}
  
twitchTV();
body {
    margin-top: 30px;
  } 
  
  .name {
    border: 2px solid black;
    margin: 5px;
    padding: 3px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="name"></div>
  <div id="bio"></div>
  <div id="stream"></div>
</div>

Comments

0

Your getJSON is making an asynchronous call. The function that you pass here will be called after variable amounts of time, depending upon network traffic and the order the that request is handled on the server. The results will come in, in a random order.

What you can do, is that instead of appending the text directly in the handler call every time you get a results, is that you can put the result in a map (JS object with members associated with the original values).

Then, you put the text together by iterating through the original list, and pulling the values that have been stored in that object. It is less efficient in some aspects, but it will have a predictable order.

var output = ""; 
var results = {};   
var twitchers = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];

function twitchTV(){
  for (var i = 0; i < twitchers.length; i++){
    var channelName = twitchers[i];
    var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/' + channelName + '/';      
    $.getJSON(apiQueryBio, function(json) {            
         results[channelName] = json["name"];
         output = generateOutputt();
    });     
  }    
}

function generateOutputt() {
    var output1 = "";
    for (var i = 0; i < twitchers.length; i++){
        var channelName = twitchers[i];
        output1 += '<div class="name">' + results[channelName] + '</div>';
            $("#name").html(output1); 
    }
    return output1;
}

Note that generateOutputt will be called many times, once for every time that you get results. But the results will be in the right order.

Comments

0

As the responses are coming in async, you need to do the ordering by yourself. Store the results in an array and rerender the whole array on each response.

Here's an example where it sort's the array by the order in twitchers.

function twitchTV(){
    var twitchers = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var output = "";
    var results = [];
    for (var i = 0; i < twitchers.length; i++){
      var channelName = twitchers[i];
      var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/' + channelName + '/';      
      $.getJSON(apiQueryBio, function(json) {            
        results.push(json);
        results.sort(function(a,b) {
           return twitchers.indexOf(a.name) - twitchers.indexOf(b.name);
        });
        renderItems(results);
      });     
    }    
  }

  function renderItems(results) {
   $("#name").html('');        
   var output = '';
   for (var i = 0; i < results.length; i++) {
      output += '<div class="name">' + results[i].name + '</div>';

   }
   $("#name").html(output);        
  }

  twitchTV();

Working fiddle

Comments

0

Here is a try

  function twitchTV(){
  /// Add div and reorder them
  function AddDiv(div){
  $("#name").append(div);
  var divs =$("#name").find(".name");
    var divs = divs.sort(function (a, b) {
        return $(a).html() > $(b).html();
    });
      $("#name").append(divs); 
  }
  
    var twitchers = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var output = "";    
    for (var i = 0; i < twitchers.length; i++){
      var channelName = twitchers[i];
      var apiQueryBio = 'https://wind-bow.glitch.me/twitch-api/users/' + channelName + '/';      
      $.getJSON(apiQueryBio, function(json) {            
            AddDiv('<div class="name">' + json["name"] + '</div>');
      });     
    } 
    }

  twitchTV();
  body {
    margin-top: 30px;
  } 
  
  .name {
    border: 2px solid black;
    margin: 5px;
    padding: 3px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="name"></div>
  <div id="bio"></div>
  <div id="stream"></div>
</div>

Comments

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.