停止 jQuery 中所有活动的 ajax 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1802936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 12:10:07  来源:igfitidea点击:

Stop all active ajax requests in jQuery

jqueryajax

提问by umpirsky

I have a problem, when submitting a form all active ajax request fail, and that triggers error event.

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

How to stop all active ajax requests in jQuery without trigerring error event?

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

回答by Darin Dimitrov

Every time you create an ajax request you could use a variable to store it:

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

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

Then you can abort the request:

然后你可以中止请求:

request.abort();

You could use an array keeping track of all pending ajax requests and abort them if necessary.

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

回答by mkmurray

The following snippet allows you to maintain a list (pool) of request and abort them all if needed. Best to place in the <HEAD>of your html, beforeany other AJAX calls are made.

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

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

回答by grr

Using ajaxSetup is not correct, as is noted on its doc page. It only sets up defaults, and if some requests override them there will be a mess.

使用ajaxSetup 是不正确的,如其文档页面所述。它只设置默认值,如果某些请求覆盖它们,则会出现混乱。

I am way late to the party, but just for future reference if someone is looking for a solution to the same problem, here is my go at it, inspired by and largely identical to the previous answers, but more complete

我参加聚会已经很晚了,但仅供将来参考,如果有人正在寻找同一问题的解决方案,这是我的做法,受到之前答案的启发并且与之前的答案基本相同,但更完整

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

回答by Andy Ferra

Here's what I'm currently using to accomplish that.

这是我目前用来实现这一目标的方法。

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

Note: _.each of underscore.js is present, but obviously not necessary. I'm just lazy and I don't want to change it to $.each(). 8P

注意:underscore.js 的 _.each 是存在的,但显然不是必需的。我只是懒惰,不想将其更改为 $.each()。8P

回答by refik

Give each xhr request a unique id and store the object reference in an object before sending. Delete the reference after an xhr request completes.

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

To cancel all request any time:

随时取消所有请求:

$.ajaxQ.abortAll();

Returns the unique ids of canceled request. Only for testing purposes.

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

Working function:

工作功能:

$.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;
    }
  };

})();

Returns an object with single function which can be used to add more functionality when required.

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

回答by Dharmesh patel

I found it too easy for multiple requests.

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

step1:define a variable at top of page:

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

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

step2:set beforeSend in all ajax requests:

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

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

step3:use it whereever you required:

步骤 3:在任何需要的地方使用它:

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

回答by kofifus

I extended mkmurray and SpYk3HH answer above so that xhrPool.abortAll can abort all pending requests of a given url:

我扩展了上面的 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;
});

Usage is same except that abortAll can now optionally accept a url as a parameter and will cancel only pending calls to that url

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

回答by the Hampster

I had some problems with andy's code, but it gave me some great ideas. First problem was that we should pop off any jqXHR objects that successfully complete. I also had to modify the abortAll function. Here is my final working code:

我在使用 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();
            });

I didn't like the ajaxComplete() way of doing things. No matter how I tried to configure .ajaxSetup it did not work.

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

回答by Steven

I have updated the code to make it works for me

我已经更新了代码以使其对我有用

$.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);
        }
    }
});

回答by onassar

Throwing my hat in. Offers abortand removemethods against the xhrPoolarray, and is not prone to issues with ajaxSetupoverrides.

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

/**
 * Ajax Request Pool
 * 
 * @author Oliver Nassar <[email protected]>
 * @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);
});