在jQuery中停止所有活动的ajax请求
我有一个问题,当提交表单所有活动的ajax请求失败,并触发错误事件。
如何在jQuery中停止所有活动的ajax请求而不引发错误事件?
每次创build一个ajax请求时,都可以使用一个variables来存储它:
var request = $.ajax({ type: 'POST', url: 'someurl', success: function(result){} });
那么你可以中止请求:
request.abort();
你可以使用一个数组跟踪所有挂起的Ajax请求,并在必要时放弃它们。
以下片段允许您维护请求的列表( 池 ),并在需要时将其全部中止。 在进行任何其他AJAX调用之前 ,最好把它放在你的html的<HEAD>
中。
<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>
使用ajaxSetup是不正确的 ,正如它的文档页面所述。 它只设置默认值,如果有一些请求覆盖它们,会有一个混乱。
我对这个晚会太晚了,但是如果有人正在寻找同样的问题的解决scheme,我只是为了将来的参考,这里是我的发现,它的灵感来源于以前的答案,而且基本上与之前的答案完全相同,但是更完整
// 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);
这是我目前用来完成的。
$.xhrPool = []; $.xhrPool.abortAll = function() { _.each(this, function(jqXHR) { jqXHR.abort(); }); }; $.ajaxSetup({ beforeSend: function(jqXHR) { $.xhrPool.push(jqXHR); } });
注意:每一个underscore.js都存在,但显然不是必须的。 我只是懒惰,我不想把它改为$ .each()。 8P
为每个xhr请求提供一个唯一的ID,并在发送之前将对象引用存储在对象中。 xhr请求完成后删除引用。
随时取消所有请求:
$.ajaxQ.abortAll();
返回已取消请求的唯一标识号。 仅用于testing目的。
工作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; } }; })();
返回具有单个function的对象,可用于在需要时添加更多function。
我发现它太容易多个请求。
第一步:在页面顶部定义一个variables:
xhrPool = []; // no need to use **var**
第二步:设置beforeSend中的所有ajax请求:
$.ajax({ ... beforeSend: function (jqXHR, settings) { xhrPool.push(jqXHR); }, ...
第三步:使用它,无论你需要:
$.each(xhrPool, function(idx, jqXHR) { jqXHR.abort(); });
我在安迪的代码上遇到了一些问题,但是它给了我一些很棒的点子。 首先问题是我们应该popup任何成功完成的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()方法。 不pipe我怎么试着configuration.ajaxSetup,它都不起作用。
我在上面扩展了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可以select接受一个url作为参数,并且只会取消对该url的未决调用
我已经更新了代码,使其适用于我
$.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); } } });
抛出我的帽子。提供abort
和remove
xhrPool
数组的方法,并不容易出现与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); });
最好使用独立代码…..
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++]); } };
同样重要的是:假设你想注销,并且用定时器生成新的请求:因为会话数据是每个新引导更新的(也许你可以告诉我在说Drupal,但这可能是任何使用会话的站点)。 。我不得不通过search和replace来查看所有的脚本,因为我有很多东西在不同的情况下运行:顶部的全局variables:
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'); }
制作一个所有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++]); } };
以下是如何在任何点击时将其挂钩(如果您的页面正在放置多个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()