adlius45
adlius45

Reputation: 41

Wait for all XHR on a page to finish in JavaScript

In my javascript file for a page, I would like to execute some scripts after all the XHR have returned. I know that there is ajaxStop() for XHR requests through jquery, but since I am using Mithril and it has its own wrapper around Ajax, I can't really use ajaxStop(). I have also tried some other solutions like

function isAllXhrComplete(){
    window.activeAjaxCount--;
    if (window.activeAjaxCount === 0){
        //execute something here.
    }

}

(function(open) {
    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
        this.addEventListener("load", isAllXhrComplete());
        open.call(this, method, url, async, user, pass);
    };
})(XMLHttpRequest.prototype.open);


(function(send) {
    XMLHttpRequest.prototype.send = function (data) {
        window.activeAjaxCount++;
        send.call(this, data);
    };
})(XMLHttpRequest.prototype.send);

But it seems that since all the XHR calls are fired separately, the window.activeAjaxCount would always be 1 or 0, thus triggering the execution of script on every finished XHR request.

Is there any good ways to wait for all XHR requests to return?

Upvotes: 3

Views: 2097

Answers (1)

t.niese
t.niese

Reputation: 40862

Your mistake is here:

this.addEventListener("load", isAllXhrComplete());

the isAllXhrComplete is not passed as callback, because you immediately call it. Instead the result of the isAllXhrComplete() call is passed.

You have to write:

this.addEventListener("load", isAllXhrComplete);

Beside that you should really take care when you wrap existing functions. A correct way would be:

(function(send) {
   XMLHttpRequest.prototype.send = function () {
      window.activeAjaxCount++;
      return send.apply(this, arguments);
   };
})(XMLHttpRequest.prototype.send);

The important part is that you return the result of the original function, and that you use apply to pass all possible arguments. Otherwise you might break code in future, if the signature of those functions is changed.

Your need to do the same with the open wrapper:

(function(open) {
  XMLHttpRequest.prototype.open = function() {
    this.addEventListener("load", isAllXhrComplete);
    return open.apply(this, arguments);
  };
})(XMLHttpRequest.prototype.open);

Upvotes: 3

Related Questions