使用jQuery中止Ajax请求

有没有可能使用jQuery,我取消/中止Ajax请求还没有收到响应?

682785 次浏览

您无法召回请求,但您可以设置一个超时值,之后将忽略响应。有关jQuery AJAX选项,请参阅此页面。我相信如果超过超时期限,您的错误回调将被调用。每个AJAX请求都已经有一个默认超时。

您也可以在请求对象上使用abort()方法,但是,虽然它会导致客户端停止侦听事件,但它可能可能不会阻止服务器处理它。

这是一个#0请求,这意味着一旦它被发送,它就在那里。

如果你的服务器因为AJAX请求而启动了一个非常昂贵的操作,你能做的最好的就是打开你的服务器监听取消请求,并发送一个单独的AJAX请求通知服务器停止它正在做的任何事情。

否则,只需忽略AJAX响应。

大多数jQuery Ajax方法返回一个XMLHttpRequest(或等效的)对象,因此您可以只使用abort()

看留档:

var xhr = $.ajax({type: "POST",url: "some.php",data: "name=John&location=Boston",success: function(msg){alert( "Data Saved: " + msg );}});
//kill the requestxhr.abort()

更新:从jQuery 1.5开始,返回的对象是名为jqXHR的本机XMLHttpRequest对象的包装器。此对象似乎公开了所有本机属性和方法,因此上述示例仍然有效。请参阅jqXHR对象(jQuery API留档)。

更新2:从jQuery 3开始,ajax方法现在返回一个带有额外方法(如abort)的Promise,因此上面的代码仍然有效,尽管返回的对象不再是xhr。请参阅3.0博客在这里

更新3xhr.abort()仍然适用于jQuery 3. x。不要假设更新2是正确的。有关jQuery Github存储库的更多信息

将您所做的调用保存在数组中,然后对每个调用xhr.abort()

巨大的洞穴:您可以中止请求,但那只是客户端。服务器端可能仍在处理请求。如果您对会话数据使用PHP或ASP之类的东西,会话数据会被锁定,直到ajax完成。因此,要允许用户继续浏览网站,您必须调用#0。这会保存会话并解锁它,以便其他等待继续的页面将继续进行。如果没有这一点,可能会有几个页面等待锁定被删除。

我们只需要解决这个问题并测试三种不同的方法。

  1. 确实按照@meouw的建议取消请求
  2. 执行所有请求,但只处理上次提交的结果
  3. 只要另一个请求仍然挂起,就会阻止新的请求

var Ajax1 = {call: function() {if (typeof this.xhr !== 'undefined')this.xhr.abort();this.xhr = $.ajax({url: 'your/long/running/request/path',type: 'GET',success: function(data) {//process response}});}};var Ajax2 = {counter: 0,call: function() {var self = this,seq = ++this.counter;$.ajax({url: 'your/long/running/request/path',type: 'GET',success: function(data) {if (seq === self.counter) {//process response}}});}};var Ajax3 = {active: false,call: function() {if (this.active === false) {this.active = true;var self = this;$.ajax({url: 'your/long/running/request/path',type: 'GET',success: function(data) {//process response},complete: function() {self.active = false;}});}}};$(function() {$('#button').click(function(e) {Ajax3.call();});})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><input id="button" type="button" value="click" />

在我们的例子中,我们决定使用方法#3,因为它为服务器产生的负载更少。但我不能100%确定jQuery是否保证调用.完整()方法,这可能会产生死锁情况。在我们的测试中,我们无法重现这种情况。

我遇到了轮询的问题,一旦页面关闭,轮询就会继续进行,所以在我的原因中,用户会错过更新,因为在页面关闭后的50秒内设置了mysql值,即使我杀死了ajax请求,我想通了,使用$_SESSION设置一个var不会在轮询中自我更新,直到它结束,一个新的开始,所以我所做的是在我的数据库中设置一个值为0=offpage,当我轮询时,我查询该行并返回false;当它为0时,在轮询中查询显然会得到当前的值……

我希望这有帮助

只需使用ajax.abort(),例如,您可以在发送另一个像这样的请求之前中止任何未决的ajax请求

//check for existing ajax requestif(ajax){ajax.abort();}//then you make another ajax request$.ajax(//your code here);

我正在做一个实时搜索解决方案,需要取消可能比最新/最新请求花费更长时间的未决请求。

在我的例子中,我使用了这样的东西:

//On document readyvar ajax_inprocess = false;
$(document).ajaxStart(function() {ajax_inprocess = true;});
$(document).ajaxStop(function() {ajax_inprocess = false;});
//Snippet from live search functionif (ajax_inprocess == true){request.abort();}//Call for new request

AJAX请求可能没有按照它们启动的顺序完成。您可以选择忽略所有AJAX响应,而不是中止:

  • 创建一个计数器
  • 启动AJAX请求时增加计数器
  • 使用计数器的当前值为请求“盖章”
  • 在成功回调中,将戳与计数器进行比较,以检查它是否是最近的请求

代码的大致轮廓:

var xhrCount = 0;function sendXHR() {// sequence number for the current invocation of functionvar seqNumber = ++xhrCount;$.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {// this works because of the way closures workif (seqNumber === xhrCount) {console.log("Process the response");} else {console.log("Ignore the response");}});}sendXHR();sendXHR();sendXHR();// AJAX requests complete in any order but only the last// one will trigger "Process the response" message

jsFiddle上的演示

正如该线程上的许多人所注意到的,仅仅因为请求在客户端被中止,服务器仍然会处理请求。这给服务器造成了不必要的负载,因为它正在做我们已经停止在前端监听的工作。

我试图解决的问题(其他人也可能遇到)是,当用户在输入字段中输入信息时,我想触发对Google Instant类型感觉的请求。

为了避免触发不必要的请求并保持前端的敏捷,我做了以下操作:

var xhrQueue = [];var xhrCount = 0;
$('#search_q').keyup(function(){
xhrQueue.push(xhrCount);
setTimeout(function(){
xhrCount = ++xhrCount;
if (xhrCount === xhrQueue.length) {// Fire Your XHR //}
}, 150);
});

这基本上每150ms发送一个请求(您可以根据自己的需要自定义变量)。如果您无法理解这里到底发生了什么,请在if块之前将xhrCountxhrQueue记录到控制台。

做这样的事情总是最好的做法。

var $request;if ($request != null){$request.abort();$request = null;}
$request = $.ajax({type : "POST", //TODO: Must be changed to POSTurl : "yourfile.php",data : "data"}).done(function(msg) {alert(msg);});

但是,如果您检查if语句以检查ajax请求是否为空,那就更好了。

只需调用xhr.abort(),无论是jQuery ajax对象还是本机XMLHTTPRequest对象。

例子:

//jQuery ajax$(document).ready(function(){var xhr = $.get('/server');setTimeout(function(){xhr.abort();}, 2000);});
//native XMLHTTPRequestvar xhr = new XMLHttpRequest();xhr.open('GET','/server',true);xhr.send();setTimeout(function(){xhr.abort();}, 2000);

没有可靠的方法来做到这一点,我甚至不会尝试,一旦请求在旅途中;合理反应的只有方法是忽略响应。

在大多数情况下,它可能发生在这样的情况下:用户过于频繁地点击触发许多连续XHR的按钮,在这里你有很多选择,要么阻止按钮直到XHR返回,或者甚至不触发新的XHR,而另一个正在运行,暗示用户向后倾斜-或者丢弃任何等待的XHR响应,但最近。

以下代码显示了启动和中止Ajax请求:

function libAjax(){var req;function start(){
req =    $.ajax({url: '1.php',success: function(data){console.log(data)}});
}
function stop(){req.abort();}
return {start:start,stop:stop}}
var obj = libAjax();
$(".go").click(function(){

obj.start();

})


$(".stop").click(function(){
obj.stop();

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><input type="button" class="go" value="GO!" ><input type="button" class="stop" value="STOP!" >

我已经分享了一个demo,它演示了如何取消AJAX请求——如果数据没有在预定义的等待时间内从服务器返回。

超文本标记语言:

<div id="info"></div>

js代码:

var isDataReceived= false, waitTime= 1000;$(function() {// Ajax request sent.var xhr= $.ajax({url: 'http://api.joind.in/v2.1/talks/10889',data: {format: 'json'},dataType: 'jsonp',success: function(data) {isDataReceived= true;$('#info').text(data.talks[0].talk_title);},type: 'GET'});// Cancel ajax request if data is not loaded within 1sec.setTimeout(function(){if(!isDataReceived)xhr.abort();},waitTime);});

如果xhr.abort();导致页面重新加载,

然后您可以在中止之前设置onreadystatechange以防止:

// ↓ prevent page reload by abort()xhr.onreadystatechange = null;// ↓ may cause page reloadxhr.abort();

您可以使用以下命令中止任何连续的ajax调用

<input id="searchbox" name="searchbox" type="text" />
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script><script type="text/javascript">var request = null;$('#searchbox').keyup(function () {var id = $(this).val();request = $.ajax({type: "POST", //TODO: Must be changed to POSTurl: "index.php",data: {'id':id},success: function () {    
},beforeSend: function () {if (request !== null) {request.abort();}}});});</script>

这是我基于上面许多答案的实现:

  var activeRequest = false; //global varvar filters = {...};apply_filters(filters);
//function triggering the ajax requestfunction apply_filters(filters){//prepare data and other functionalitiesvar data = {};//limit the ajax callsif (activeRequest === false){activeRequest = true;}else{//abort if another ajax call is pending$request.abort();//just to be sure the ajax didn't complete before and activeRequest it's already falseactiveRequest = true;}
$request = $.ajax({url : window.location.origin + '/your-url.php',data: data,type:'POST',beforeSend: function(){$('#ajax-loader-custom').show();$('#blur-on-loading').addClass('blur');},success:function(data_filters){
data_filters = $.parseJSON(data_filters);              
if( data_filters.posts ) {$(document).find('#multiple-products ul.products li:last-child').after(data_filters.posts).fadeIn();}else{return;}$('#ajax-loader-custom').fadeOut();},complete: function() {activeRequest = false;}});}