-2

In my website I have a page which sends some XHR requests to the same server, the problem is if the user click on any link to navigate to any other pages on the same server, the browser blocks and waits until all XHR finish first, then navigate, which can take ~10 seconds.

I already implemented the XHR abort solution, it's working but the browser still waiting for XHR responses. In my opinion xhr.abort() is only to prevent calling xhr.onload() only, but in reality the browser still waiting for the response from XHR.

How can I force the browser to close and destroy an XHR request immediately using JavaScript?

Code is a copy-paste of this one.

All this is happens in the same server. If I navigate to another server the browser navigate immediately, while if the link is in the same server the browser wait first to finish all XHR requests.

ShellX3
  • 51
  • 8
  • Are those 10+ XHR requests to the same server the user is then trying to navigate to? Because otherwise, that just isn't how browsers work, they'll happily navigate away from a page when XHR requests are outstanding. They throttle the number of requests to a given origin, which makes me wonder if **maybe** something like this is possible if that's interfering with going to the next page, but... Please provide a [mre] showing the behavior. – T.J. Crowder Apr 20 '22 at 13:35
  • Yes, All this is happens in the same server. – ShellX3 Apr 20 '22 at 13:46
  • And yes, if I navigate to another server the browser navigate immediately, while if the link is in the same server the browser wait first to finish all XHR requests. – ShellX3 Apr 20 '22 at 13:50

1 Answers1

0

The problem is that the browser limits the number of requests to a single origin, and apparently when navigating, Chrome (at least) waits until it can request the new page before tearing down the old one, resulting in the delay. (In constrast, Firefox does not wait, in my tests.)

If you cancel the requests that are outstanding when leaving the page, they stop preventing the browser from navigating. For instance, if you make your requests through a wrapper function:

const requests = new Set();
function request(...args) {
    const xhr = new XMLHttpRequest(...args);
    xhr.addEventListener("load", removeRequest);
    xhr.addEventListener("error", removeRequest);
    requests.add(xhr);
    return xhr;
}
function removeRequest() {
    requests.delete(this);
}

...and then cancel them when leaving the page:

window.onbeforeunload = () => {
    for (const xhr of [...requests]) {
        xhr.abort();
        requests.delete(xhr);
    }
};

That solves the problem (for me, using Chrome; it also works on Firefox, but Firefox didn't hold things up in the first place).

I wasn't sure onbeforeunload would work, given all the restrictions that are placed on it by modern browsers, but it did and I guess cancelling a request doesn't try to start something new, and doesn't take too long, so that makes sense.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    In addition I also added the session close writing in the server side, more information here: https://stackoverflow.com/a/970843/13682781 – ShellX3 Apr 20 '22 at 14:22