Twitch.tv help with offline channels - Resolved

I need help with twitch.tv - getting nowhere. ;-(
I need logo, name and status of the channels that are in array [“ESL_SC2”, “OgamingSC2”, “cretetion”, “freecodecamp”, “storbeck”, “habathcx”, “RobotCaleb”, “noobs2ninjas”, “brunofin”, “comster404”]-(given in instructions).
I have no problem with channels that do not exist, or with channels that are online.
But the one that are offline — I can not get, unless I cheat and use a constant for path. (see commented part of the code with IT WORKS)

However in a loop, even that channels[i] is correct (console.log check), somehow if I form the path
as concatenation of strings - all of the sudden the name is undefined and logo does not exist.
Here is my code (I got this by trial and error and do not know if it is correct to look under streams, and channels
for online, offline respectively)

here is my codepen link: [http://codepen.io/zvukmiro/pen/LbYZdY?editors=0001]

here is my code
$(document).ready(function() {
// array with channels from fcc project instructions, just so I do have all 3 kinds(online, offline and non-existing)
var channels = [“ESL_SC2”, “OgamingSC2”, “cretetion”, “freecodecamp”, “storbeck”, “habathcx”, “RobotCaleb”, “noobs2ninjas”, “brunofin”, “comster404”];
// id for twitch got when registered at twitch.tv, instructions:
//Go to https://www.twitch.tv/settings/connections
//Log in to twitch and scroll down to “Register your application”
//Add a name for your project and set the Redirect URI to your CodePen project URL without the editors part, register, now see your Client ID.
var id = “i0fk7wb0ymfkv9dz7g7oo02nm5y7ukz”;
var url = “https://api.twitch.tv/kraken/streams/”;
var urlOff = “https://api.twitch.tv/kraken/channels/”;
//iterate thru different channels and get if they are broadcasting, or offline, or do not exist
for (var i = 0; i < channels.length; i++) {
var url_channel = url + channels[i] + “?client_id=” + id + “&callback=?”;
console.log(channels[i]);
var url_channelOff=urlOff+ channels[i] +"?client_id="+ id + “&callback=?”;
//THIS WORKS: var url_channelOff=“https://api.twitch.tv/kraken/channels/noobs2ninjas?client_id=i0fk7wb0ymfkv9dz7g7oo02nm5y7ukz&callback=?";
console.log(url_channel);
console.log(url_channelOff);
$.getJSON(url_channel).done(function(dataChannels) {
var logo;
var status;
var name;
if (dataChannels.error) {
logo = “http://res.cloudinary.com/dplyxbspe/image/upload/v1478562512/A_Logo_06_dlhnan.jpg”;
name = dataChannels.message;
status = dataChannels.error;
$(”#list").prepend("

" + “
” + “” + “
” + “
” + name + “
”+"
"+status+ “
”);
              } //end of if
          else if(dataChannels.stream === null){
            //that means they are offline
            
            $.getJSON(url_channelOff, function(dataOff){
              logo=dataOff.logo;
              name=dataOff.display_name;
              status="Offline";
              //console.log(name);
              $("#list").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<a href='https://api.twitch.tv/kraken/streams/'" + channels[i]+">"+"<img src='" + logo + "'>"+"</a>" + "</div>" + "<div class='col-md-4'>" + name + "</div>"+"<div class='col-md-4'>"+status+ "</div></div>");

            });

          }  
          else{
            //this mean they are online - include message what they are broadcasting
            logo=dataChannels.stream.channel.logo;
            name=dataChannels.stream.channel.display_name;
            status=dataChannels.stream.channel.status;
            
            $("#list").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<img src='" + logo + "'>" + "</div>" + "<div class='col-md-4'>" + name + "</div>"+"<div class='col-md-4'>"+status+ "</div></div>");
          }  
          }); // end of getJSON.done call
      } // end of for loop

  });

There are a couple of problems that I can see. First,

30  else if(dataChannels.stream === null){
                //that means they are offline

This could also mean the user doesn’t exist, so you’re making another API call unnecessarily. The other problem is that you’re using a for loop to make these calls and counting on the variable i to be the same value at the beginning and the end of the AJAX call. The way JavaScript works is that it sends functions, $.getJSON() for instance, to an event loop. It’s a common mistake, even among more seasoned developers coming to JavaScript, to assume that functions will be executed in the same order they were put into that loop, and that these functions will have access to all the same variables they had a few milliseconds ago. However, by the time $.getJSON() gets a response, i has changed. You have two options:

  1. Enable the babel preprocessor and use the ES6 let keyword in the for loop.
for (let i = 0; i < channels.length; i++) {
  //...
  1. Store the current value of i in a closure with each iteration, and reference that variable instead.
for (var i = 0; i < channels.length; i++) {
  var current_idx = i;
  var url_channel = url + channels[current_idx] + "?client_id=" + id + "&callback=?";
  var url_channelOff=urlOff+ channels[current_idx] +"?client_id="+ id + "&callback=?"
  // ...
1 Like

Hi PortableStick,

thanks a lot for taking the time to look into this.
I made changes according to your recommendations.
I used let for i, but also tried with var index=i. The results stayed unchanged.
The really strange thing is that since it works for 2 online channels and 2 non existing channels,
the i, is changing each time it runs. For example brunofin is at i=2, then at i=7, etc.
I tried both with var i, let i, and var index=i and the i for particular channel or its place in array
keeps changing. Do you maybe know why is this?

As for my original problem of not being able to get the name and logo for offline channels, that is unresolved.
It works if as a url I put a constant. Am I wrong to use “https://api.twitch.tv/kraken/channels/” + channel Name + id, as a path for getJSON for offline channels?

Here is the code again:

$(document).ready(function() {
// array with channels from fcc project instructions, contains all 3 kinds of channels: online, offline and non-existing
var channels = [“ESL_SC2”, “OgamingSC2”, “cretetion”, “freecodecamp”, “storbeck”, “habathcx”, “RobotCaleb”, “noobs2ninjas”, “brunofin”, “comster404”];

  var id = "i0fk7wb0ymfkv9dz7g7oo02nm5y7ukz";
  const url = "https://api.twitch.tv/kraken/streams/";
  const urlOff = "https://api.twitch.tv/kraken/channels/";
  //iterate thru different channels and get if they are broadcasting, or offline, or do not exist
  for (let i = 0; i < channels.length; i++) {
    var url_channel = url + channels[i] + "?client_id=" + id + "&callback=?";
    var url_channelOff=urlOff+ channels[i] +"?client_id="+ id + "&callback=?";
    //THIS WORKS: var url_channelOff="https://api.twitch.tv/kraken/channels/noobs2ninjas?client_id=i0fk7wb0ymfkv9dz7g7oo02nm5y7ukz&callback=?";
    $.getJSON(url_channel).done(function(dataChannels) {
          var logo;
          var status;
          var name;
          if (dataChannels.error) {
            logo = "http://res.cloudinary.com/dplyxbspe/image/upload/v1478562512/A_Logo_06_dlhnan.jpg";
            name = dataChannels.message;
            status = dataChannels.error;
            $("#list").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<img src='" + logo + "'>" + "</div>" + "<div class='col-md-4'>" + name + "</div>"+"<div class='col-md-4'>"+status+ "</div></div>");
          } //end of if
          else if(dataChannels.stream === null){
            //that means they are offline
            $.getJSON(url_channelOff, function(dataOff){
              logo=dataOff.logo;
              name=dataOff.display_name;
              status="Offline";
              $("#list").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<a href='https://api.twitch.tv/kraken/streams/'" + channels[i]+">"+"<img src='" + logo + "'>"+"</a>" + "</div>" + "<div class='col-md-4'>" + name + "</div>"+"<div class='col-md-4'>"+status+ "</div></div>");
            });// end of second getJSON call
          }// end of else if
          else{
            //this mean they are online 
            logo=dataChannels.stream.channel.logo;
            name=dataChannels.stream.channel.display_name;
            status=dataChannels.stream.channel.status;
            $("#list").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<img src='" + logo + "'>" + "</div>" + "<div class='col-md-4'>" + name + "</div>" + "<div class='col-md-4'>" + status + "</div></div>");
          }//end of else
    }); // end of getJSON.done first call
  } // end of for loop
  });//end of doc ready

Hi Zvukmiro

I’m having the same problem with offline streams.

Did you find a solution?

Thanks

Hi,
The offline channels require different ajax call. The reason is what you get back from the twitch.tv as a response.
You can not access the logo or the name, if you send request with the same path as online.
const url = “https://api.twitch.tv/kraken/streams/”;
const urlOff = “https://api.twitch.tv/kraken/channels/”;
So for one, the path is different.

So you would have to have a separate ajax call for offline channels, once you deteremine that they are off line.
Here is part of my code, showing you the ajax call for offline. You can stop here, and come up with your own code.
** there is a for loop iterating thru array of channels**
** this is one of the if statements that is first checking that channel is offline**
** use your own client ID that you got when registered on twitch tv not zzz
else if(dataChannels.stream === null){
//getJSON call did not work, but ajax does - do not know why
$.ajax({
type:“GET”,
url:“https://api.twitch.tv/kraken/channels/”+channels[i],
headers:{‘Client-ID’:‘zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz’,
},
success:function(dataOff){
//console.log(channels[i]);
//console.log(url_channelOff);
logo=dataOff.logo;
name=channels[i];
status=“Offline”;
//now take your results and prepend them to html element that you are reserved for showing results
}//end of success
});// end of ajax call
}// end of else if

Regards,
Zorana

Great call. I was having the same issue, and both options worked for me. Thank you!

What worked for me was using .forEach instead of a for loop. Worth a shot if you’re still having issues.