Reputation: 5
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>
Upvotes: 0
Views: 91
Reputation: 33726
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.
$.when()
receives the deferred objects.apply
to pass the deferred objects through an array.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>
Upvotes: 1
Reputation: 1253
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>
Upvotes: 0
Reputation: 4870
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>
Upvotes: 0
Reputation: 2804
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();
Upvotes: 0
Reputation: 5598
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.
Upvotes: 0