Home > Software engineering >  How do you ensure an XMLHttpRequest() has received its full response before continuing?
How do you ensure an XMLHttpRequest() has received its full response before continuing?

Time:01-26

I'm looping XMLHttpRequests and for each response I'm pushing it to an array.

I use async/await to try to ensure that I only return my array of responses once all of the responses are recieved.

For some reason, with no error, this method is not working and I am not getting the full response array.

// looping requests in function

const getFetched = async () => {
  return Promise.all(
    await getURLArray().then(async (requestURLArray) => {
      const fetchedData = [];

      await requestURLArray.map((value, index) => {
        const requestUrl = value;
        const Http = new XMLHttpRequest();
        Http.open("GET", requestUrl);
        Http.responseType = "json";
        Http.send();

        Http.onreadystatechange = (e) => {
          if (Http.response === null) return;      
          fetchedData.push(Http.response);
        };       
      });

      return fetchedData;
    })
  );
};

// calling function to make requests

const fetchedData = await getFetched.then((fetched) => {
  // from the above, if I log fetched it has the correct data in it
  // but this is because of the console updating it after the promise
  // so if I log fetched.length it is 0 - meaning it hasnt properly fetched the data yet
})

What can I do to ensure that the Http request is completely finished before returning the array of responses?

CodePudding user response:

You can use the Promise object to wrap the XMLHttpRequest and return the promise that resolves with the response.

const fetchData = (requestUrl) => {
    return new Promise((resolve, reject) => {
        const Http = new XMLHttpRequest();
        Http.open("GET", requestUrl);
        Http.responseType = "json";
        Http.send();

        Http.onreadystatechange = (e) => {
            if (Http.readyState === 4 && Http.status === 200) {
                resolve(Http.response);
            }
        };
    });
};

const getFetched = async () => {
    const requestURLArray = await getURLArray();
    const fetchedData = await Promise.all(requestURLArray.map(fetchData));
    return fetchedData;
};

This way, the function fetchData returns a promise that resolves with the response, and Promise.all will wait for all the promises to resolve before returning the result.

CodePudding user response:

Consider using fetch instead, as it works with Promises.

return Promise.all(
    (await getURLArray()).map(url => fetch(url).then(res => res.json()))
);
  • Related