2009-11-26 142 views

回答

238

每当你创建你可以使用一个变量来存储它一个Ajax请求:

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

然后你就可以中止请求:

request.abort(); 

你可以使用一个数组保存所有的曲目等待ajax请求并在必要时中止它们。

+10

是的,是的,http://plugins.jquery.com/project/ajaxqueue可以提供帮助。 – umpirsky 2009-11-27 12:00:45

+0

THXs,我添加了一个标志,因为我同时使用了多个请求 – jcho360 2012-09-19 14:56:54

+0

这里是简单的工作示例:http://stackoverflow.com/a/42312101/3818394 – 2017-02-18 06:53:54

36

这是我目前用来完成的。

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

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

+2

我有一个稍微修改过的解决方案,它非常适合我即将发布的内容。 – mkmurray 2012-01-12 19:52:19

+6

这会泄漏内存。 'aboutAll'应该从阵列中移除元素。另外当请求完成时,它应该从列表中删除它自己。 – Behrang 2012-06-04 06:15:38

+3

@BehrangSaeedzadeh你应该也发布了一个改进版本。 – mattsven 2013-08-11 06:30:33

4

我和安迪的代码存在一些问题,但它给了我一些很棒的点子。首先问题是我们应该弹出成功完成的任何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,它都不起作用。

+7

我认为如果他们没有按照特定的顺序完成,你可能会在错误的请求中调用弹出窗口? – jjmontes 2011-11-30 13:34:55

+1

是的,你想做切片而不是流行。我有一个稍微修改的解决方案,我即将发布。 – mkmurray 2012-01-12 19:52:44

173

以下代码片段允许您维护请求的列表(),并在需要时将它们全部中止。最好放置在您的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> 
+2

你钉了它。谢谢 – Trip 2012-04-13 09:03:16

+2

@mkmurray - 关于在IE8 initalization我似乎得到'对象不支持属性或方法'indexOf''?我怀疑它可能是http://stackoverflow.com/a/2608601/181971或者只是交换到http://stackoverflow.com/a/2608618/181971? – Tim 2012-05-09 05:26:20

+3

@grr是正确的,请参阅他的答案并检查[ajaxSetup](http://api.jquery.com/jQuery.ajaxSetup/)的文档。 – kzfabi 2013-08-13 14:14:21

111

使用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); 
+5

比从未更好的迟到,伟大的工作! – 2012-07-12 10:19:08

+0

好工作,帮助了我! – devmonster 2012-09-23 08:58:03

+0

如何称呼终止()方法从其他函数中调用 – 2015-09-30 21:28:58

17

为每个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; 
    } 
    }; 

})(); 

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

0

同样重要的是:假设你想注销,并且你正在用计时器产生新的请求:因为会话数据每更新一次引导程序(也许你可以告诉我在说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'); 
} 
3

我的代码更新使它适用于我

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

以下是如何挂钩(如果您的页面正在放置多个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() 
4

我伸出mkmurray和SpYk3HH答案的上方,使得xhrPool.abortAll可以中止所有等待的请求指定网址的

$.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的未决呼叫

2

投掷我的帽子。提供abortremove针对xhrPool arr的方法ay,并且不容易出现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); 
}); 
1

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

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++]); 
    } 
}; 
2

让所有的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++]); 
    } 
}; 
11

我觉得太容易多个请求。

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

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

第二步:集beforeSend在所有Ajax请求:

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

第三步:等。无论您需要使用它:

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

这是按原样! – 2017-06-22 19:51:52

+0

我只是想:) – 2017-10-28 05:19:10

+0

这会泄漏内存,正如https://stackoverflow.com/a/6618288/1772379所做的那样,并且出于完全相同的原因。 – 2017-11-08 22:13:48