Alternatives to Synchronous JSON call

Alternatives to Synchronous JSON call
0

#1

I am working on the Twitch app challenge and I ran through the problem where the loop traversing the list of channels couldn’t properly get the respective data for each channel.

 var channels = [ "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb",  "noobs2ninjas" ];

I was using this code

  for (let i = 0; i <= channels.length - 1; i++) {
       $.getJSON("https://wind-bow.glitch.me/twitch-api/users/" + channels[i], function (data) {
                $("#"+channels[i]).html(data);        //the div IDs where the JSON data will be displayed are named after the channel 
 });

The above approach didn’t work due to the time taken by getJSON() to gather data from the stream which was causing issues. I found a solution for it, which I don’t quite understand well but apparently it is delivering the required result. Turns out, I can add ajaxSetup() and put async as false and from there everything just works.

  for (let i = 0; i <= channels.length - 1; i++) {
       $.getJSON("https://wind-bow.glitch.me/twitch-api/users/" + channels[i], function (data) {
            $.ajaxSetup({
              async: false
            }); 
            $("#"+channels[i]).html(data); 
 });

I’m getting the desired output but here is the problem. I can see a visible delay for a few moments when before the divs load the JSON data. The page looks as if it is frozen. I’m curious to know if there is some other method to execute the same thing, because it is likely that with bigger amount of data the delay will consequently get bigger. Furthermore, I plan to add the feature to auto refresh the online-offline status of channels every few seconds so frequent JSON calls is bound to slow the page. Please help.
Also, I merely copy-pasted the code from a stack overflow answer for getting a synchronous output using JSON. Can anyone explain why was there an issue in the first place and how the ajaxSetup() function takes care of it?


#2

When you make synchronous calls, your page is definitely going to appear frozen until the response comes back. That is why it is so important to understand how to make asynchronous calls instead.

You did not post your entire code or a link to your entire code, so I would be guessing if I tried to make a suggestion on how you can salvage your project when minimal changes. My guess is that you are trying to access information in data outside the getJSON callback function, but that is just a guess. Post your entire code and we can help you work it out.


#3


Here is the link to the pen.


#4

OK, I am just going to focus on the for loop and explain why your current code (using asynchronous mode of getJSON) is not working. First, I removed the part that was making it synchronous.

  for (let i = 0; i <= channels.length - 1; i++) {
    divID="#"+channels[i];
    $.getJSON("https://wind-bow.glitch.me/twitch-api/users/" + channels[i], function (data) { 
      $(divID).html(data.name);  
    });
   
    $.getJSON("https://wind-bow.glitch.me/twitch-api/streams/" + channels[i], function (data) { 
      if(data.stream==null){
        console.log(channels[i]+" is inactive");
        $(divID).addClass("channel-offline");  
       $(divID).removeClass("channel-online");    
      }else{
        console.log(channels[i]+" is active");
        $(divID).addClass("channel-online"); 
        $(divID).removeClass("channel-offline");  
      }       
    });
  }

In the above code, you assign divID the current channel. The getJSON is called and while it is waiting for a response to come back so you can put the name of the channel in the applicable div with the following line:

$(divID).html(data.name);  

the for loop has already finished looping, so in the last iteration of the for loop, divID is “noobs2ninjas” because channels[7] is “noobs2ninjas”. The div with id=“noobs2ninjas” is the last div showing, which is why only it gets anything in it. As far as the name that actually gets displayed in this div, that will depend on which response happens to come back at the time.

How do you fix? Move the divID initialization to be inside the getJSON callback function. Since you are using let i, i will still be preserved during the getJSON’s call, so the correct channel will show.

The next issue is how to use your other getJSON to add/remove the applicable class based on if the stream is null or not. Currently, you have the second getJSON after the first getJSON. With this order, the classes will appear to be randomly added/removed from the channel divs. That is because channels[i] will be different values that what was called using channels[i] in the streams url.

How to fix? You will need to do two things to make this work. First, you will nest the entire second getJSON portion inside the first getJSON callback function (at the end). I will not give away the second thing needed, but I will tell you it will be similar to what I explained on fixing the first getJSON call (HINT: divID).


#5

Thanks. It totally worked. Now when I see it it looks so simple but I never could’ve done without your help. Once again, thanks a ton :grinning: