Execute A Function When All xmlHttpRequests Are Complete

时间秒杀一切 提交于 2021-01-27 19:09:17

问题


BRIEF

I have a website which gets data from an API. So it makes some post and get requests to a server once the website is opened. Let us assume it makes 5 different xmlHttpRequests as soon as the page loads but we cannot exactly know the time each call takes from start to finish.

FOR EXAMPLE

Call to one endpoint takes 2 seconds to complete and the other one takes 1 second to complete. So that means after 2 seconds both the calls are said to be finished.

TO-DO

I want to execute a function after all the xmlHttpRequests are complete because I am using window.performance.getEntries() to fetch all the requests initiated by the webpage and send it to my server as I am doing a web analytics project in which I need to access the times taken by each network request and convert the data into a chart.

EXTRA-QUESTION OR HINT

Is there any event that can be attached to the window as shown below to listen for all the network calls and execute my piece of code when all are finished.

      window.addEventListener("load", function (event) {
       //execute some code here
      }

In the load event I am not able to capture all the requests by using performance.getEntries() because load fires before the ajax calls are finished.

As shown above I ask. Is there any trick or any event or anything in JavaScript by which we can wait untill all the XMLHTTPREQUESTS are finished and then execute some code.


回答1:


WORKING SOLUTION

We can track browser AJAX calls using the code below :

  const ajaxCallStatus = () => {
   window.ajaxCalls = 0; // initial ajax calls
   window.ajaxEndpoints = []; // keeping track of all ajax call urls (endpoints) 
   const origOpen = XMLHttpRequest.prototype.open;
   XMLHttpRequest.prototype.open = function() {
   window.ajaxCalls++;
   this.addEventListener('load', (event) => {
    if (!window.ajaxEndpoints.includes(event['currentTarget'].responseURL)) {
      window.ajaxEndpoints.push(event['currentTarget'].responseURL);
    }
    window.ajaxCalls--;
    switch (window.ajaxCalls) {
    case 0: // when ajax calls finish this runs
      addData(window.ajaxEndpoints);
    break;
    }
     });
    origOpen.apply(this, arguments);
    }
   }

ADD DATA FUNCTION - Used for sending data to some backend.

function addData(arr, origOpen) { 
   XMLHttpRequest.prototype.open = origOpen;
   axios.post('url', data)
  .then((res) => console.log(res))
  .catch((err) => console.log(err));
}



回答2:


I would suggest you to wrap your requests in promises and then use Promise.all(...) like so:

const makeRequest = () => {
    return new Promise((resolve, reject) => {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                resolve(xhttp.responseText); // On success, resolve the promise
            } else {
                reject(); // On failure, reject it
            }
        };
        xhttp.open("GET", "filename", true); // Needs to be set to your needs. This is just an example
        xhttp.send();
    });
}

// This waits until all promises are resolved
const [result1, result2] = await Promise.all(makeRequest(), makeRequest());

// do stuff here with your results
console.log(result1);
console.log(result2);

PS: Basic Ajax example is from here, but just swap it for yours and create parameters or similar to make the requests you actually need

OR

You could use a library like Axios for Ajax requests, which already returns Promises by default. Check it out here: https://github.com/axios/axios



来源:https://stackoverflow.com/questions/63503441/execute-a-function-when-all-xmlhttprequests-are-complete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!