API request call inside for loop

API request call inside for loop
0

#1

Could someone please explain why this does not work?

Here’s my JS code:

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

$(document).ready(function() {
  
  for(i=0;i<streamersArray.length; i++) {
  
    var myRequest = new XMLHttpRequest();
    myRequest.open('GET','https://wind-bow.glitch.me/twitch-api/users/' + streamersArray[i]); 
    myRequest.onload = function() {
      var streamerInfo = JSON.parse(myRequest.responseText);
      console.log(streamerInfo); 
    };
  
    myRequest.send();
    
  };
    
});

All I get is the API info of the last item in the array.

There’s nothing more to it, but if you wish to have a link to my codepen, here it is: https://codepen.io/sk1995/pen/zpJYNZ

At the moment, all I want is to understand how to make an API request call for every single item in the array. :thinking:

Thanks.


#2

XHR requests are terrible and you should avoid writing them. They’re difficult to read and bug prone. The Fetch API is the new browser native way to do AJAX. When I refactored your code to use Fetch, it worked just fine. It’s also easier to read. I’ll give you a head start because it’s quite different:

fetch('https://wind-bow.glitch.me/twitch-api/users/' + streamersArray[i])
    .then(response => {
      if(response.ok) return response.json();
      throw new Error(response.statusText)  // throw an error if there's something wrong with the response
    })
    .then(function handleData(data) {
        // your happy data goes here
    )) 
    .catch(function handleError(error) {
        // handle errors here
    }) 

Also, you’re missing a variable keyword in your loop declaration:

for(let i=0;i<streamersArray.length; i++)

If you’re not familiar with the new JavaScript features, let is similar to var. For technical reasons involving variable scope, you want to use let for all loop declarations, but you can use var if it makes you feel more comfortable. Just don’t omit the keyword entirely.


#3

Thank you very much.

I will take your advice.


#4

Well, I’m beyond puzzled.

How does this even happen?!

Here’s my code:

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

for(let i=0;i<streamersArray.length; i++) {

  fetch('https://wind-bow.glitch.me/twitch-api/users/' + streamersArray[i])
    .then(response => {
      if(response.ok) return response.json();
      throw new Error(response.statusText);
    })
    .then(function handleData(data) {
    var displayName = data.display_name
    $("#listofstreamers").append("<div class='streamer"+i+" streamer' > "+displayName+" </div>"); 
    })
    .catch(function handleError(error) {
    
    });
  
  fetch('https://wind-bow.glitch.me/twitch-api/streams/' + streamersArray[i])
    .then(response => {
      if(response.ok) return response.json();
      throw new Error(response.statusText);
    })
    .then(function handleData(data) {
      
      var onlineStatus = data.stream;
      var streamStatus = data.channel.status; 
      console.log(data.stream);
      if(onlineStatus == null) {
        $(".streamer"+i).append("<p>Offline</p>");
      }
      else {
        $(".streamer"+i).append("<p>"+streamStatus+"</p>");
      }
    })
    .catch(function handleError(error) {
    
    })
  
    
  
};

My problems are on my second Fetch, inside .then(function handleData(data) { })

This is the weirdest thing. If I place that console.log ABOVE both variables, it works just fine. If i place BELOW them, it suddenly doesn’t work. How does that even happen?

UPDATE: Okay, I managed to get rid of that problem by not declaring any variables. I Still do not understand why it happened. Could someone please explain?

Now, I’ve got a new problem. The whole thing is just inconsistent. Sometimes it shows the offline status and the current channel status if online, and sometimes it doesn’t.

How do I go about this? I’d like to know why this doesn’t work, and perhaps get some hints and tips as to how to structure my code to make it all work.


#5

Nest your 2nd fetch inside the handleData callback function of your first fetch to fix your issues.

The problem is since fetch is asynchronous, the 2nd fetch does not wait until the 1st fetch is complete before starting. So, you could definitely have situations where when the 2nd fetch response comes back for a particular username, the first fetch’s response has not come back. In this scenario, when you use the following code to append the applicable status of the streamer, the selector does not find that div, because it has not been created yet.

      if(data.stream == null) {
        $(".streamer"+i).append("<p>Offline</p>");
      }
      else {
        $(".streamer" + i).append("<p>" + data.stream.channel.status + "</p>");
      }

#6

Thanks Randell! :slight_smile: