Issues with ajax request

Hello, after some time off coding I decided I would dive right in. I am currently doing the twitch app, but I am having some issues with the ajax request. I am using an array to store streamers in it, then I decided to use the for loop to iterate over the array and display every streamer on the page(that will come later on, haven’t implemented that yet in the JS code). So i run everything, I get no errors in console, but the only request that goes through is the last streamer. In the console, I can see all the previous requests are cancelled. Now I am using the new Twitch API, but I searched in their documentation if something revolving this issue was mentioned but I couldn’t find anything. Bellow is the console picture and the JS code.

var client_id = 'i0hx9uhbef1qw9egt0howi026f3izk';
var xhttp = new XMLHttpRequest();
var streamers = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
var urlChannels = "https://api.twitch.tv/helix/users?login=OgamingSC2";
var data;
var channelGrid = document.getElementById("channels-grid");




window.onload = function() {
    
    for(var i = 0; i < streamers.length; i++) {
        var url = "https://api.twitch.tv/helix/users?login=" + streamers[i];
        xhttp.open('GET', url);
        xhttp.setRequestHeader('Client-ID', client_id);
        xhttp.onload = function() {
            if(xhttp.status === 200) {
                data = xhttp.responseText;
                console.log(data);
                console.log("Code 200");
            }
            else {
                console.log("Error");
            }
        }
        xhttp.send();

    }
}

So you have a variable outside the loop called xhttp. You then start the loop, which starts to set up the request, the request takes time, the loop goes onto the next one, which starts another request using that xhttp variable. That basically overwrites it, so the original request is cancelled, and the next one it tried, loop goes onto the next one and so on, so only the last one can ever finish.

The Ajax request is asynchronous; JS will not wait around and stop the loop until it completes then start another request. So you are just overwriting the request every iteration

You have a couple of issues. First, you only create one instance of XMLHttpRequest, so you are only going to have one time where xhttp.onload is going to execute. Second, the reason only the last streamer in streamers returns results, is because XMLHttpRequest is asynchronous and does not prevent other code (the for loop) from executing before a response comes back and the onload part kicks in. Only the last streamer returns data, because the for loop runs and attempts to open the created url for each streamer, but since it takes time for the response to come back from the twitch API, the for loop finishes and only the last url opened with xhttp.open is seen. Why? Because it is the only time, where a response can actually come back before being reassigned another url by the for loop.

There are a couple of ways of fixing this. One involves using a IIFE (Immediately Invoked Function Expression) or the simplest solution of changing var i = 0 in the for loop to let i = 0 plus you need to make a new instance of XMLHttpRequest for each stream. To do this, one way is to create an empty object (called xhttp) before the for loop starts and then assign a new property (i) which will represent each XMLHttpRequest instance. For example, you would write (inside the for loop):

xhttp[i] = new XMLHttpRequest();

and then refer to xhttp[i] everywhere else inside the for loop instead of xhttp.

1 Like

I really appreciate the time you took to write all that. Really helped me a ton and also now I understand http requests a lot more than before. Thank you it works great now :smile:.