等待页面上的所有XHR完成JavaScript

时间:2016-07-19 15:09:59

标签: javascript ajax

在我的页面javascript文件中,我想在所有XHR返回后执行一些脚本。我知道通过jquery对XHR请求有ajaxStop(),但由于我使用的是Mithril并且它有自己的Ajax包装器,我实际上不能使用ajaxStop()。 我也尝试过其他一些解决方案,比如

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);

但似乎由于所有XHR调用都是单独触发的,window.activeAjaxCount总是为1或0,因此会在每个完成的XHR请求中触发脚本执行。

是否有任何好方法可以等待所有XHR请求返回?

1 个答案:

答案 0 :(得分:2)

你的错误在这里:

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

isAllXhrComplete未作为回调传递,因为您立即调用它。而是传递isAllXhrComplete()调用的结果。

你必须写:

this.addEventListener("load", isAllXhrComplete);

除此之外,在包装现有函数时应该非常小心。一个正确的方法是:

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

重要的是你return原始函数的结果,并使用apply传递所有可能的参数。否则,如果更改了这些函数的签名,您将来可能会破坏代码。

您需要对open包装器执行相同的操作:

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