When I check the web browser console it says the “json.log is undefined” and I can’t figure out why. Any help would be appreciated!
…
$(’.clickOffline’).click(function(event) {
//Go through each 'user' for display_name and put in div
for (var i = 0; i < streamURL.length; i++) {
$.getJSON(streamURL[i], function(val) {
if (val.stream!==null) {
var divBoxes = '';
$.getJSON(userURL[i], function(json) {
divBoxes += '<div class="user" style="background-color: #CCFFCC;">' + "<img src='"+json.logo + "' class='pic'>" + '<a href="https://www.twitch.tv/'+json.display_name+'"target="_blank">'+json.display_name + '</a>'+'<br>' + '<p style="color:red; font-size:14px;text-align: center;">'+ 'Offline'+'</p>'+ '</div>';
$('.twitch').html(divBoxes);
}); //end 'userURL' getJSON
}
}) //end 'stream' getJSON
} // end 'for loop'
hmmm I’ve fiddled for over an hour - indeed everything works (I’ve console.logged, alerts and all until you make the inner call to streamUrl[i…and there nothing. Sorry - I’m sure it’s something totally logical but I’m not experienced enough to see what.
I haven’t looking into why but the second json call for the offline button is not working (specifically line 86). Code inside the function is not executing (line 86 to 92).
While looking at this I noticed this offline button function is only matching the online streams up to this point, rather than the offline ones.
The problem seems to be related to nesting one AJAX request inside another. It’s not easy/obvious why the nested call isn’t firing. But I would guess your loop completes before the 2nd AJAX response is received.
I re-worked your click handler using slightly different loops and chained jQuery promises. I think it’s easier to follow than inline anonymous callbacks. I’m no pro at promises, but as I understand it each .then() returns another promise, so subsequent .then() blocks “wait” for the preceding blocks to complete before fiting. There’s still a lot of room for code optimization here, but hopefully you see how this works.
Pseudo …
For each user,
Get their channel object
Then get their stream object
Then filter
Then update DOM.
//Offline function
$('.clickOffline').click(function(event) {
$('.twitch').empty(); // empty the output element
users.forEach(function(user) {
$.getJSON(twitchChannel + user)
.then(getStreams)
.then(filterObject)
.then(updateDom);
});
});
function getStreams(channel) {
// get the channels stream
return $.getJSON(twitchStreams + channel.name)
.then(function(st) {
// return object consisting of channel + stream
return {
channel: channel,
stream : st
};
});
}
function filterObject(data) {
// filter streams, returning 'null' streams
return (data.stream.stream === null) ? data : false;
}
function updateDom(data) {
var divBoxes;
if (data) {
divBoxes = [
'<div class="user" style="background-color: #CCFFCC;">',
"<img src='" + data.channel.logo + "' class='pic'>",
'<a href="https://www.twitch.tv/' + data.channel.display_name + '"target="_blank">',
data.channel.display_name,
'</a>' + '<br>',
'<p style="color:red; font-size:14px;text-align: center;"> Offline </p>',
'</div>'
].join('');
}
$('.twitch').append(divBoxes);
}
Thanks a lot! This code works and now I’m undertaking the task of understanding it because I haven’t been introduced to the concepts of jQuery promises functions.
I haven’t been introduced to the concepts of jQuery promises
Jquery seems to just extend regular JavaScript promises, so start with traditional promises. You don’t have to master promises to use them - jquery and angular ajax functions create promises and you consume them with .then() blocks.