Good evening.
I'm currently working on an app that uses the twitch API.
For the first time I had to use the forEach JS command. But for some reason I cannot figure out, it seems kind of messy, as if for each wasn't firing in the right order, and as if the function is sometimes executed several time before the next array's element is fired.
I built a codepen that set the problem apart :
https://codepen.io/Hadrienallemon/pen/bLZJeX
As you can see in the pen, if you click several time on the test button, the result aren't always in the right order.
Here's the code :
HTML :
<button id="button">test button</button>
<div class="wrapper"></div>
CSS :
html,body{
height : 100%;
width : 100%;
}
.wrapper{
height : 90%;
width : 100%;
}
.awnser{
background-color : tomato;
margin : 50px auto;
width : 60%;
min-height : 10%;
}
JS :
var lives = ["nat_ali","krayn_live","streamerhouse","merry"];
$("button").on("click",function(){
lives.forEach(function(element){
$(".wrapper").empty();
$.getJSON("https://wind-bow.glitch.me/twitch-api/streams/"+ element +"?callback=?",function(quote){
if (quote.stream != null){
$(".wrapper").append("
<div class = 'awnser'>
<p>"+quote.stream.game+"</p>
</div>");
}
else{
$(".wrapper").append("
<div class = 'awnser'>
<span class = 'circle' style ='text-align : right'>
<p style = 'display : inline-block;'>offline</p>
</span>
</div>");
}
})
$.getJSON("https://wind-bow.glitch.me/twitch-api/users/"+ element +"?callback=?",function(quote){
console.log(quote.logo);
$(".awnser:last-child").append("
<div style ='width : 10%; height : 10%;'>"+ quote.display_name +"
<img src = '"+quote.logo+"' style = 'max-width : 100%;max-height : 100%;'></div>");
})
})
})
$.getJSON
is asynchronous. Your forEach
starts the calls in a given order, but they can complete in any order at all, completely chaotically.
If you want to process their completions in order, you can save each promise from $.getJSON
in an array, wait for them to complete with $.when
(they'll run in parallel, but your callback won't run until they're all done), and then process the results:
$.when.apply($, lives.map(element => $.getJSON(/*...*/))
.done((...results) => {
// All calls are done, process results
results.forEach(result => {
// ...
});
});
jQuery's $.when
will call your done
callback with an argument for each of the promises you pass it. In the above, we gather those up in an array via a rest parameter and then loop through it.
Or with pre-ES2015 syntax using the arguments
pseudo-array:
$.when.apply($, lives.map(function(element) { return $.getJSON(/*...*/)})
.done(function() => {
var results = Array.prototype.slice.call(arguments);
// All calls are done, process results
results.forEach(function(result) {
// ...
});
});