Home > OS >  Running multiple XMLHttpRequests in a loop from an array only returns last request
Running multiple XMLHttpRequests in a loop from an array only returns last request

Time:07-23

Let me start by saying I'm fairly new to JS (more familiar with looping languages like C), so I have not been able to understand various examples well enough to implement into my code.

Essentially what I am trying to do is request YouTube APIs in a loop using an array of channel ID's. From that request, parse out the video count and return it into an array. (End goal is to save said array and then compare it next time code is run to be able to display a list of channels with new videos)

The below code is the part of my program that handles the API requests for new videos, but it only returns the value from the LAST request. To fix this, I have tried implementing various forms of promise, async/await, and re-writing the code to run in a different order. So far all attempts have either failed to rectify the issue, or broke the code altogether.

//(example) channel list declared in a separate .js file
const lists = [
{"value": "UC5f5IV0Bf79YLp_p9nfInRA", "name": "How Ridiculous      ", "group": "1", "count": ""},
{"value": "UCRijo3ddMTht_IHyNSNXpNQ", "name": "Dude Perfect        ", "group": "1", "count": ""},
{"value": "UCY1kMZp36IQSyNx_9h4mpCg", "name": "Mark Rober          ", "group": "2", "count": ""}];

//vars declared at start of script
const ApiKey = "AIzaSyDlb2NRFdp61zp28aXGzXBCgQQTSkjAK2I";
var countdata = new XMLHttpRequest();
var Api2Url;
const URLstart2 = "https://www.googleapis.com/youtube/v3/channels?id=";
const URLend2 = "&fields=items(,statistics(,videoCount))&part=statistics";
var API2Response;
var newlists;
var newlistoutput;

//eventually this function is called
for (let index = 0; index < lists.length; index  ) {
      Api2Url = URLstart2   lists[index].value "&key=" ApiKey  URLend2;
      countdata.onload = function() {
        API2Response = JSON.parse(this.responseText);
        lists[index].count = API2Response.items[0].statistics.videoCount;
      }
      countdata.open("GET", Api2Url, true);
      countdata.send();
    }
  console.log(lists);

// code missing here to filter contents of "lists" by items with new values, and place into "newlists"
    // write data to Count property
    // create new difference property with count - old count properties
    // filter to only objects with difference property >0

// this code will run once values have been compared (into HTML <div id=chaninfo><div>)
for (let X in newlists) {
      newlistoutput  = newlists[X].name   "  --->   "   newlists[X].difference   " New Videos <br>";
    };
    document.getElementById("chaninfo").innerHTML = newlistoutput;

// shift values from count to old count properties
// save object for next time - localStorage?

Code for comparing new vs old values has not been written yet, since this depends on how I have to format the output of this function.

I would have expected this to add the video count to each of the channel object "count" properties. However, it only adds the value to the last object in the array. Additionally, console shows 'XHR failed loading: GET "".' for each item except the last one.

I am assuming the request is getting modified too fast for the results to come back and be added back to the array, but I have not been able to figure out how to force the code to wait on completion before moving on to the next request.

CodePudding user response:

You should use a new XHR object for each request

for (let index = 0; index < lists.length; index  ) {
  let countdata = new XMLHttpRequest();
  Api2Url = URLstart2   lists[index].value "&key=" ApiKey  URLend2;
  countdata.onload = function() {
    API2Response = JSON.parse(this.responseText);
    lists[index].count = API2Response.items[0].statistics.videoCount;
  }
  countdata.open("GET", Api2Url, true);
  countdata.send();
}

Since you want to use lists after the for loop I suggest taking a look at fetch and await/async.

CodePudding user response:

The instance of XHR can not be reused.

  • Related