【问题标题】:Stop all active ajax requests in jQuery在 jQuery 中停止所有活动的 ajax 请求
【发布时间】:2010-12-20 15:36:21
【问题描述】:

我有一个问题,提交表单时所有活动的 ajax 请求都失败了,这会触发错误事件。

如何在不触发错误事件的情况下停止 jQuery 中所有活动的 ajax 请求?

【问题讨论】:

    标签: jquery ajax


    【解决方案1】:

    每次创建 ajax 请求时,都可以使用变量来存储它:

    var request = $.ajax({
        type: 'POST',
        url: 'someurl',
        success: function(result){}
    });
    

    然后你可以中止请求:

    request.abort();
    

    您可以使用一个数组来跟踪所有待处理的 ajax 请求并在必要时中止它们。

    【讨论】:

    • THXs,我添加了一个 FLAG,因为我同时使用了多个请求
    • 这是一个简单的工作示例:stackoverflow.com/a/42312101/3818394
    • 我在函数中有 ajax 调用,我该如何中止它?
    • 该变量必须声明为全局变量,以便在进行 ajax 调用时从另一个函数访问它。示例:多文件上传过程。
    【解决方案2】:

    以下 sn-p 允许您维护请求列表 (pool) 并在需要时中止它们。最好放置在您的 html 的 <HEAD> 中,进行任何其他 AJAX 调用之前。

    <script type="text/javascript">
        $(function() {
            $.xhrPool = [];
            $.xhrPool.abortAll = function() {
                $(this).each(function(i, jqXHR) {   //  cycle through list of recorded connection
                    jqXHR.abort();  //  aborts connection
                    $.xhrPool.splice(i, 1); //  removes from list by index
                });
            }
            $.ajaxSetup({
                beforeSend: function(jqXHR) { $.xhrPool.push(jqXHR); }, //  annd connection to list
                complete: function(jqXHR) {
                    var i = $.xhrPool.indexOf(jqXHR);   //  get index for current connection completed
                    if (i > -1) $.xhrPool.splice(i, 1); //  removes from list by index
                }
            });
        })
    </script>
    

    【讨论】:

    • @mkmurray - 在 IE8 中初始化我似乎得到了 Object doesn't support property or method 'indexOf' ?我怀疑它可能是stackoverflow.com/a/2608601/181971 或者只是换成stackoverflow.com/a/2608618/181971
    • @grr 是对的,请查看他的答案并查看文档中的 ajaxSetup
    • @Tim - 正如 Steven 建议的那样,而不是 var index = $.xhrPool.indexOf(jqXHR);使用: var index = $.inArray(jqXHR, $.xhrPool);
    • @mkmurray: 它显示 TypeError: jqXHR.abort 对我来说不是一个函数。 :(
    • abortAll方法有一点逻辑错误,在这个答案stackoverflow.com/a/45500874/1041341中修复了
    【解决方案3】:

    使用 ajaxSetup is not correct,如其文档页面所述。它只设置默认值,如果某些请求覆盖了它们,就会一团糟。

    我迟到了,但如果有人正在寻找相同问题的解决方案,仅供参考,这是我的尝试,灵感来自之前的答案,并且与之前的答案基本相同,但更完整

    // Automatically cancel unfinished ajax requests 
    // when the user navigates elsewhere.
    (function($) {
      var xhrPool = [];
      $(document).ajaxSend(function(e, jqXHR, options){
        xhrPool.push(jqXHR);
      });
      $(document).ajaxComplete(function(e, jqXHR, options) {
        xhrPool = $.grep(xhrPool, function(x){return x!=jqXHR});
      });
      var abort = function() {
        $.each(xhrPool, function(idx, jqXHR) {
          jqXHR.abort();
        });
      };
    
      var oldbeforeunload = window.onbeforeunload;
      window.onbeforeunload = function() {
        var r = oldbeforeunload ? oldbeforeunload() : undefined;
        if (r == undefined) {
          // only cancel requests if there is no prompt to stay on the page
          // if there is a prompt, it will likely give the requests enough time to finish
          abort();
        }
        return r;
      }
    })(jQuery);
    

    【讨论】:

    • 如何从其他函数调用 abort() 方法?
    • abort 是一个函数,而不是一个方法。你通常在同一个封装中调用它,如果你需要在封装之外使用它,你可以删除函数名前的“var”,它将成为一个全局可用的函数
    • 嗨,有人能解释一下 r 什么时候是未定义的吗?
    【解决方案4】:

    这是我目前用来完成此任务的方法。

    $.xhrPool = [];
    $.xhrPool.abortAll = function() {
      _.each(this, function(jqXHR) {
        jqXHR.abort();
      });
    };
    $.ajaxSetup({
      beforeSend: function(jqXHR) {
        $.xhrPool.push(jqXHR);
      }
    });
    

    注意:_.each 下划线.js 都存在,但显然没有必要。我只是懒惰,我不想将其更改为 $.each()。 8P

    【讨论】:

    • 我有一个稍微修改过的解决方案,效果很好,我正要发布。
    • 这会泄漏内存。 aboutAll 应该从数组中删除元素。另外,当请求完成时,它应该从列表中删除自己。
    • @BehrangSaeedzadeh 你应该也发布一个改进的版本。
    【解决方案5】:

    给每个 xhr 请求一个唯一的 id 并在发送之前将对象引用存储在一个对象中。 在 xhr 请求完成后删除引用。

    随时取消所有请求:

    $.ajaxQ.abortAll();
    

    返回已取消请求的唯一 ID。仅用于测试目的。

    工作功能:

    $.ajaxQ = (function(){
      var id = 0, Q = {};
    
      $(document).ajaxSend(function(e, jqx){
        jqx._id = ++id;
        Q[jqx._id] = jqx;
      });
      $(document).ajaxComplete(function(e, jqx){
        delete Q[jqx._id];
      });
    
      return {
        abortAll: function(){
          var r = [];
          $.each(Q, function(i, jqx){
            r.push(jqx._id);
            jqx.abort();
          });
          return r;
        }
      };
    
    })();
    

    返回一个具有单一功能的对象,可用于在需要时添加更多功能。

    【讨论】:

      【解决方案6】:

      我发现多个请求太容易了。

      第一步:在页面顶部定义一个变量:

        xhrPool = []; // no need to use **var**
      

      step2:在所有ajax请求中设置beforeSend:

        $.ajax({
         ...
         beforeSend: function (jqXHR, settings) {
              xhrPool.push(jqXHR);
          },
          ...
      

      第三步:在你需要的地方使用它:

         $.each(xhrPool, function(idx, jqXHR) {
                jqXHR.abort();
          });
      

      【讨论】:

      • 这会泄漏内存,就像stackoverflow.com/a/6618288/1772379 所做的那样,并且出于完全相同的原因。
      • 写 JavaScript 的方式真的很糟糕。
      • 可能在最后你可以清除/清空 xhrPool 数组
      【解决方案7】:

      我扩展了上面的 mkmurray 和 SpYk3HH 答案,以便 xhrPool.abortAll 可以中止所有待处理的请求给定 url

      $.xhrPool = [];
      $.xhrPool.abortAll = function(url) {
          $(this).each(function(i, jqXHR) { //  cycle through list of recorded connection
              console.log('xhrPool.abortAll ' + jqXHR.requestURL);
              if (!url || url === jqXHR.requestURL) {
                  jqXHR.abort(); //  aborts connection
                  $.xhrPool.splice(i, 1); //  removes from list by index
              }
          });
      };
      $.ajaxSetup({
          beforeSend: function(jqXHR) {
              $.xhrPool.push(jqXHR); //  add connection to list
          },
          complete: function(jqXHR) {
              var i = $.xhrPool.indexOf(jqXHR); //  get index for current connection completed
              if (i > -1) $.xhrPool.splice(i, 1); //  removes from list by index
          }
      });
      $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
          console.log('ajaxPrefilter ' + options.url);
          jqXHR.requestURL = options.url;
      });
      

      用法相同,只是 abortAll 现在可以选择接受一个 url 作为参数,并且只会取消对该 url 的挂起调用

      【讨论】:

        【解决方案8】:

        我在使用 andy 的代码时遇到了一些问题,但它给了我一些很棒的想法。第一个问题是我们应该弹出任何成功完成的 jqXHR 对象。我还必须修改 abortAll 函数。这是我的最终工作代码:

        $.xhrPool = [];
        $.xhrPool.abortAll = function() {
                    $(this).each(function(idx, jqXHR) {
                                jqXHR.abort();
                                });
        };
        $.ajaxSetup({
            beforeSend: function(jqXHR) {
                    $.xhrPool.push(jqXHR);
                    }
        });
        $(document).ajaxComplete(function() {
                    $.xhrPool.pop();
                    });
        

        我不喜欢 ajaxComplete() 做事的方式。无论我如何尝试配置 .ajaxSetup,它都不起作用。

        【讨论】:

        • 我认为如果 pop 未按特定顺序完成,您可能会调用错误的请求?
        • 是的,你想做切片而不是弹出。我有一个稍微修改过的解决方案,我即将发布。
        【解决方案9】:

        我已更新代码以使其适合我

        $.xhrPool = [];
        $.xhrPool.abortAll = function() {
            $(this).each(function(idx, jqXHR) {
                jqXHR.abort();
            });
            $(this).each(function(idx, jqXHR) {
                var index = $.inArray(jqXHR, $.xhrPool);
                if (index > -1) {
                    $.xhrPool.splice(index, 1);
                }
            });
        };
        
        $.ajaxSetup({
            beforeSend: function(jqXHR) {
                $.xhrPool.push(jqXHR);
            },
            complete: function(jqXHR) {
                var index = $.inArray(jqXHR, $.xhrPool);
                if (index > -1) {
                    $.xhrPool.splice(index, 1);
                }
            }
        });
        

        【讨论】:

          【解决方案10】:

          扔掉我的帽子。针对xhrPool 数组提供abortremove 方法,并且不容易出现ajaxSetup 覆盖的问题。

          /**
           * Ajax Request Pool
           * 
           * @author Oliver Nassar <onassar@gmail.com>
           * @see    http://stackoverflow.com/questions/1802936/stop-all-active-ajax-requests-in-jquery
           */
          jQuery.xhrPool = [];
          
          /**
           * jQuery.xhrPool.abortAll
           * 
           * Retrieves all the outbound requests from the array (since the array is going
           * to be modified as requests are aborted), and then loops over each of them to
           * perform the abortion. Doing so will trigger the ajaxComplete event against
           * the document, which will remove the request from the pool-array.
           * 
           * @access public
           * @return void
           */
          jQuery.xhrPool.abortAll = function() {
              var requests = [];
              for (var index in this) {
                  if (isFinite(index) === true) {
                      requests.push(this[index]);
                  }
              }
              for (index in requests) {
                  requests[index].abort();
              }
          };
          
          /**
           * jQuery.xhrPool.remove
           * 
           * Loops over the requests, removes it once (and if) found, and then breaks out
           * of the loop (since nothing else to do).
           * 
           * @access public
           * @param  Object jqXHR
           * @return void
           */
          jQuery.xhrPool.remove = function(jqXHR) {
              for (var index in this) {
                  if (this[index] === jqXHR) {
                      jQuery.xhrPool.splice(index, 1);
                      break;
                  }
              }
          };
          
          /**
           * Below events are attached to the document rather than defined the ajaxSetup
           * to prevent possibly being overridden elsewhere (presumably by accident).
           */
          $(document).ajaxSend(function(event, jqXHR, options) {
              jQuery.xhrPool.push(jqXHR);
          });
          $(document).ajaxComplete(function(event, jqXHR, options) {
              jQuery.xhrPool.remove(jqXHR);
          });
          

          【讨论】:

            【解决方案11】:

            创建一个包含所有 ajax 请求的池并中止它们.....

            var xhrQueue = []; 
            
            $(document).ajaxSend(function(event,jqxhr,settings){
                xhrQueue.push(jqxhr); //alert(settings.url);
            });
            
            $(document).ajaxComplete(function(event,jqxhr,settings){
                var i;   
                if((i=$.inArray(jqxhr,xhrQueue)) > -1){
                    xhrQueue.splice(i,1); //alert("C:"+settings.url);
                }
            });
            
            ajaxAbort = function (){  //alert("abortStart");
                var i=0;
                while(xhrQueue.length){ 
                    xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
                }
            };
            

            【讨论】:

              【解决方案12】:
              var Request = {
                  List: [],
                  AbortAll: function () {
                      var _self = this;
                      $.each(_self.List, (i, v) => {
                          v.abort();
                      });
                  }
              }
              var settings = {
                  "url": "http://localhost",
                  success: function (resp) {
                      console.log(resp)
                  }
              }
              
              Request.List.push($.ajax(settings));
              

              当你想中止所有的 ajax 请求时,你只需要调用这行代码

              Request.AbortAll()
              

              【讨论】:

                【解决方案13】:

                最好使用独立代码.....

                var xhrQueue = []; 
                
                $(document).ajaxSend(function(event,jqxhr,settings){
                    xhrQueue.push(jqxhr); //alert(settings.url);
                });
                
                $(document).ajaxComplete(function(event,jqxhr,settings){
                    var i;   
                    if((i=$.inArray(jqxhr,xhrQueue)) > -1){
                        xhrQueue.splice(i,1); //alert("C:"+settings.url);
                    }
                });
                
                ajaxAbort = function (){  //alert("abortStart");
                    var i=0;
                    while(xhrQueue.length){ 
                        xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
                    }
                };
                

                【讨论】:

                  【解决方案14】:

                  同样重要:假设您要注销并且正在使用计时器生成新请求:因为每次新引导程序都会更新会话数据(也许您可以说我在说 Drupal,但这可能是任何使用会话的站点)... 我必须通过搜索和替换来浏览我的所有脚本,因为我有很多东西在不同的情况下运行:顶部的全局变量:

                  var ajReq = [];
                  var canAj = true;
                  function abort_all(){
                   for(x in ajReq){
                      ajReq[x].abort();
                      ajReq.splice(x, 1)
                   }
                   canAj = false;
                  }
                  function rmvReq(ranNum){
                   var temp = [];
                   var i = 0;
                   for(x in ajReq){
                      if(x == ranNum){
                       ajReq[x].abort();
                       ajReq.splice(x, 1);
                      }
                      i++;
                   }
                  }
                  function randReqIndx(){
                   if(!canAj){ return 0; }
                   return Math.random()*1000;
                  }
                  function getReqIndx(){
                   var ranNum;
                   if(ajReq.length){
                      while(!ranNum){
                       ranNum = randReqIndx();
                       for(x in ajReq){
                      if(x===ranNum){
                       ranNum = null;
                      }
                       }
                      }
                      return ranMum;
                   }
                   return randReqIndx();
                  }
                  $(document).ready(function(){
                   $("a").each(function(){
                      if($(this).attr('href').indexOf('/logout')!=-1){          
                       $(this).click(function(){
                      abort_all();                 
                       });
                      }
                   })
                  });
                  // Then in all of my scripts I wrapped my ajax calls... If anyone has a suggestion for a 
                      // global way to do this, please post
                  var reqIndx = getReqIndx();
                  if(reqIndx!=0){
                  ajReq[reqIndx] = $.post(ajax, { 'action': 'update_quantities', iids:iidstr, qtys:qtystr },  
                  function(data){
                   //..do stuff
                   rmvReq(reqIndx);
                   },'json');
                  }
                  

                  【讨论】:

                    【解决方案15】:

                    这里介绍了如何在任何点击时将其连接起来(如果您的页面发出许多 AJAX 调用并且您正试图离开,这很有用)。

                    $ ->
                        $.xhrPool = [];
                    
                    $(document).ajaxSend (e, jqXHR, options) ->
                        $.xhrPool.push(jqXHR)
                    
                    $(document).ajaxComplete (e, jqXHR, options) ->
                        $.xhrPool = $.grep($.xhrPool, (x) -> return x != jqXHR);
                    
                    $(document).delegate 'a', 'click', ->
                        while (request = $.xhrPool.pop())
                          request.abort()
                    

                    【讨论】:

                      【解决方案16】:

                      有一个虚拟解决方案,我用它来中止所有 ajax 请求。此解决方案是重新加载整个页面。如果您不喜欢为每个 ajax 请求分配一个 ID,并且如果您在 for 循环中发出 ajax 请求,则此解决方案很好。这将确保所有 ajax 请求都被终止。

                      location.reload();
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-10-15
                        • 1970-01-01
                        • 2018-05-28
                        • 2015-03-16
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多