This js code does some pretty strange stuff. Can anyone tell me, what I am doing wrong?

This js code does some pretty strange stuff. Can anyone tell me, what I am doing wrong?
0

#1

At the bottom, there is a console.log statement that gives the length of channelName
and channelName array itself. The strange thing is length is zero while channelName is a valid array. The other strange thing with this program is that different output are displayed when alert() method is used .

$(document).ready(function(){
  
  
    
      var results = $('#resultArea');
  
  
    
      var users = ["freecodecamp", "storbeck", "terakilobyte", "habathcx","RobotCaleb","thomasballinger","noobs2ninjas","beohoff","brunofin", "comster404","esl_sc2","ogamingsc2","channelThatdoesnotExist"];
  
  
    
      var status = [];
  
  
    
      var link = [];
  
  
    
      var channelLink = [];
  
  
    
      var img = [];
  
  
    
      var channelName = [];
  
  
    
      var storeResults = function(name){
  
  
    
        var url = "https://api.twitch.tv/kraken/streams/"+name;
  
  
    
        //alert(url)
  
  
    
        $.ajax({url,success:function(json){
  
  
    
    

  
  
    
              if(json.stream)
  
  
    
               status.push("Streaming: "+json.stream.game);
  
  
    
    

  
  
    
              else
  
  
    
                status.push("Offline");
  
  
    
    

  
  
    
              link.push(json._links.channel);
  
  
    
              //alert(link)
  
  
    
              $.getJSON(link[link.length-1],function(channelJson){
  
  
    
                //alert(JSON.stringify(channelJson))
  
  
    
                channelName.push(channelJson.display_name);
  
  
    
                img.push(channelJson.logo);
  
  
    
                channelLink.push(channelJson.url);
  
  
    
    

  
  
    
              });
  
  
    
    

  
  
    
              },
  
  
    
              statusCode: {
  
  
    
              404: function() {
  
  
    
                status.push("Account doesn't exist");
  
  
    
                channelLink.push("undefined");
  
  
    
                channelName.push(name);
  
  
    
                img.push("http://s19.postimg.org/qygpcxncj/unknown.png");
  
  
    
              },
  
  
    
              422: function() {
  
  
    
                status.push("Account closed");
  
  
    
                channelLink.push("undefined");
  
  
    
                channelName.push(name);
  
  
    
                img.push("http://s19.postimg.org/qygpcxncj/unknown.png");
  
  
    
              }
  
  
    
    

  
  
    
        }});//main get Req ends
  
  
    
        return "successfully returned from getInfo"
  
  
    
      };//storeResults ends
  
  
    /******** this gives channelName 's length = 0 but gives an array containing all the names *******/
      console.log(channelName.length, channelName);
  
  
    
      //display part starts here
  
  
    
      function displayResults(){
  
  
    
              //console.log(channelName,status,channelLink,img);
  
  
    
    

  
  
    
      for(var user = 0; user < users.length; user++){
  
  
    
    

  
  
    
              var superElem = $("<div>").attr("class","row");
  
  
    
              var elem = $("<div>");
  
  
    
    

  
  
    
              elem.attr("class","col-xs-12 col-md-12")
  
  
    
             elem.append($('<div>').attr("class","col-xs-2 col-md-2").append($('<img>').attr({src:img[user]})));
  
  
    
    

  
  
    
              var nameWithLink =$('<div>').attr("class","col-xs-10 col-md-5").append();
  
  
    
              var nameLink = $('<a>').attr({href:channelLink[user],target:"_blank"});
  
  
    
              nameLink.append($('<p>').text(channelName[user]));
  
  
    
              elem.append(nameWithLink.append(nameLink));
  
  
    
              elem.append($('<div>').attr("class","col-xs-10 col-md-5").append($('<p>').text(status[user])));
  
  
    
              superElem.append(elem);
  
  
    
              results.append($('<li>').append(superElem));
  
  
    
    

  
  
    
              }
  
  
    
          }
  
  
    
    

  
  
    
    

  
  
    
      function getResults(){
  
  
    
        for(var index in users){
  
  
    
          storeResults(users[index]);
  
  
    
        }
  
  
    
        return true;
  
  
    
      }//getResult ends;
  
  
    
    getResults();
  
  
    
    displayResults();
  
  
    
    setTimeout(
  
  
    
      function(){
  
  
    
       var fimg = $('<img>').attr({src:"http://s19.postimg.org/5g4p3n90z/claping_hands.png",class:"flogo"});
  
  
    
        var footerText = $('<h2>').append(fimg);
  
  
    
        footerText.append($('<span>').text("th-th-th-that's all folks!"));
  
  
    
        $("footer").append(footerText);
  
  
    
      },2000);
    });`

#2

Just a quick glance on my phone, but it looks like you are calling the console.log for the channelName outside of your $.ajax function.

$.ajax is asychronous, meaning that it will start running and then move onto the next part of the code while it finishes. When it moves onto the console.log, the ajax may or may not be done processing. If it’s not, the channelName array will not have any data in it.

You’ll need to call the console.log within the ajax/json function to be able to access that data.

If anyone sees anything to add, or if I misread anything, please feel free to add.


#3

To expand, if I add a console.log to your code here: https://gyazo.com/b4a80fe3de1fb2ed9edeebaf99d744c8, you get this result in the console: https://gyazo.com/4af6a5a25f7d5edddf6dd5845131bc77.

Notice that the 0 length empty array log is called before the console.log that I added. It moved on to that while the asynchronous function was processing.

Let me know if you have questions!


#4

First of all, thank you very much for giving your time to this question.

When it moves onto the console.log, the ajax may or may not be done
processing. If it’s not, the channelName array will not have any data in
it.

If you ll look at screenshot , you will notice that array length is 0 but array contents are not. My question is if ajax hadd not done processing then how come array has ALL the names. The second question is what is Array[0] in screenshot? some one suggested me to check length of array[0] but it was zero too.

The Second question is why on using alert() in this code leads to different result. By different results I dont mean the order of loading.

I completely agree with you on asynchronous thing . Can you tell me a good way to do the stuff that I am trying to do in this code.


#5

To be honest, I’m not sure why that is happening. I can replicate what you have in Firefox (0 length Array with all the names) but not in Chrome. Someone more knowledgeable might be able to help with that.

As for how to use the data you generate, you need to do the rest of your processing inside the ajax/json functions.

If you do something like this:

$.ajax({
    // ajax options
    success: function (data) {
        // PROCESS data here where it is accessible
        // eg. process your arrays and display them in the html
    }
});
// DON'T do any processing of data here as it may not be ready yet.

it should work.

Essentially, you can’t do anything with the data generated by ajax calls unless you do it inside the ajax/json function. This means you’ll need to nest everything inside those functions.

There is a way to make the code stop until asynchronous functions are done using Deferred and Promises, but I can’t really comment on those as I haven’t used them.

Let me know if that helps! They’re kind of a tricky topic :slight_smile:


#6

Thanks again. Well I have completed this pro by encapsltg everyting in ajax call but I was just wondering why this happend that’s why posted this question to get brighter insight.


#7

Sorry I couldn’t help with the Array question. Hopefully someone will be able to answer, because I’m interested too now.

Good luck with the future projects!


#8

No problem buddy. All the best to you too :slight_smile:.


#9

To add to what @zaclem01 suggested… one thing you can do is create callback function(s) that are run in when a successful ajax request is processed:

function manipulateData(d) {
    // Callback to manipulate data
};

function manipulateDataAgain(d) {
    // Another callback to manipulate data
}
$.ajax({
    // ajax options
    success: function (data) {
         manipulateData(data);
         manipulateDataAgain(data);
    }
});

These callbacks can contain any jquery logic you want to use on the data.

If you want to use promises, there are several third party libraries that you can use. Here are a couple I can vouch for:


#10

Thanks. I will look into it.