使用jQuery中止Ajax请求
使用jQuery,我如何取消/中止我还没有收到回应的Ajax请求 ?
大多数jQuery Ajax方法返回一个XMLHttpRequest(或等效的)对象,所以你可以使用abort()
。
请参阅文档:
- 放弃方法 ( MSDN )。 取消当前的HTTP请求。
- abort() ( MDN )。 如果请求已经发送,则此方法将中止请求。
var xhr = $.ajax({ type: "POST", url: "some.php", data: "name=John&location=Boston", success: function(msg){ alert( "Data Saved: " + msg ); } }); //kill the request xhr.abort()
更新:从jQuery 1.5开始,返回的对象是一个名为jqXHR的原生XMLHttpRequest对象的包装。 这个对象似乎公开了所有的本地属性和方法,所以上面的例子仍然有效。 请参阅jqXHR对象 (jQuery API文档)。
更新2:截至jQuery 3,ajax方法返回一个承诺,没有额外的方法(如中止),所以这将不再工作。 在这里看到3.0博客 。 一个办法是通过xhr
属性来控制xhr对象。 这是一个简单的例子:
var xhr = new window.XMLHttpRequest(); var request = $.ajax({ url : url, xhr : function(){ return xhr; } }); xhr.abort();
您无法记起请求,但可以设置一个超时值,之后响应将被忽略。 看到这个页面的jQuery AJAX选项。 我相信,如果超时超时,你的错误callback将被调用。 每个AJAX请求已经有一个默认超时。
您也可以在请求对象上使用abort()方法,但是,当它将导致客户端停止监听事件时,它可能不会阻止服务器处理它。
这是一个asynchronous请求,意思是一旦它被发送出去。
如果您的服务器由于AJAX请求而开始了非常昂贵的操作,那么您可以做的最好的方法是打开您的服务器来侦听取消请求,并发送一个单独的AJAX请求,通知服务器停止正在进行的操作。
否则,只需忽略AJAX响应。
保存你在一个数组中的调用,然后调用xhr.abort()。
巨大的CAVEAT:你可以放弃一个请求,但这只是客户端。 服务器端仍然可以处理请求。 如果您正在使用PHP或ASP等会话数据,会话数据将被locking,直到ajax完成。 所以,为了让用户继续浏览网站,你必须调用session_write_close ()。 这将保存会话并解除locking,以等待继续的其他页面继续。 没有这个,几个页面可能正在等待锁被删除。
AJAX请求可能无法按照开始的顺序完成。 除了中止,您可以select忽略除最近一个之外的所有AJAX响应:
- 创build一个计数器
- 在启动AJAX请求时增加计数器
- 使用计数器的当前值“加盖”请求
- 在成功callback比较印记与计数器,以检查是否是最近的请求
代码的粗略轮廓:
var xhrCount = 0; function sendXHR() { // sequence number for the current invocation of function var seqNumber = ++xhrCount; $.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() { // this works because of the way closures work if (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
我们只需要解决这个问题,并testing了三种不同的方法。
- 根据@meouw的build议取消请求
- 执行所有的请求,但只处理最后提交的结果
- 只要另一个还在等待,就可以阻止新的请求
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" />
做这样的事情总是最好的做法。
var $request; if ($request != null){ $request.abort(); $request = null; } $request = $.ajax({ type : "POST", //TODO: Must be changed to POST url : "yourfile.php", data : "data" }).done(function(msg) { alert(msg); });
但是,如果您检查if语句以检查ajax请求是否为null,则会好得多。
meouw的解决scheme是正确的,但如果你对更多的控制感兴趣,那么你可以尝试jQuery的Ajaxpipe理器插件 。
我正在做一个实时search解决scheme,并需要取消可能需要比最新/最新的请求更长的未决请求。
在我的情况下,我用这样的东西:
//On document ready var ajax_inprocess = false; $(document).ajaxStart(function() { ajax_inprocess = true; }); $(document).ajaxStop(function() { ajax_inprocess = false; }); //Snippet from live search function if (ajax_inprocess == true) { request.abort(); } //Call for new request
正如线程中的许多人所指出的,仅仅因为请求在客户端被中止,服务器仍然会处理请求。 这会在服务器上造成不必要的负载,因为它正在做我们已经放弃在前端监听的工作。
我试图解决的问题(其他人也可能会遇到)是,当用户在input字段中input信息时,我想要发出Google即时types的请求。
为了避免发出不必要的请求,并保持前端的快乐,我做了以下工作:
var xhrQueue = []; var xhrCount = 0; $('#search_q').keyup(function(){ xhrQueue.push(xhrCount); setTimeout(function(){ xhrCount = ++xhrCount; if (xhrCount === xhrQueue.length) { // Fire Your XHR // } }, 150); });
这将基本上每150毫秒发送一个请求(一个variables,您可以根据自己的需要进行自定义)。 如果您无法理解这里发生了什么, xhrCount
和xhrQueue
到if块之前的控制台。
只要使用ajax.abort()例如你可以放弃任何未决的Ajax请求,然后再发送这样的一个
//check for existing ajax request if(ajax){ ajax.abort(); } //then you make another ajax request $.ajax( //your code here );
没有可靠的方法去做,而且一旦请求被移走,我甚至不会去尝试。 唯一合理的反应就是忽视这个反应。
在大多数情况下,可能会发生这样的情况:用户点击过多的button触发许多连续的XHR,这里有很多选项,要么阻止button,直到XHR返回,或者甚至不会触发新的XHR而另一个正在运行提示用户靠后 – 或放弃任何未决的XHR响应,但最近。
只要打电话给xhr。 abort()是否是jQuery ajax对象或本机XMLHTTPRequest对象。
例:
//jQuery ajax $(document).ready( var xhr = $.get('/server'); setTimeout(function(){xhr.abort();}, 2000); ); //native XMLHTTPRequest var xhr = new XMLHttpRequest(); xhr.open('GET','/server',true); xhr.send(); setTimeout(function(){xhr.abort();}, 2000);
我有轮询的问题,一旦页面closures,民意调查继续进行,所以在我的原因中,用户会错过更新,因为在closures页面后的下一个50秒,将会设置一个mysql值,即使我杀了ajax请求,我弄清楚,使用$ _SESSION来设置一个var不会更新自己的轮询,直到它结束,并开始一个新的,所以我所做的是在我的数据库中设置一个值为0 = offpage,而我轮询我查询该行并返回false; 当它是0,因为在轮询中查询会显示当前值…
我希望这有助于
以下代码显示了启动以及中止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!" >
我已经分享了演示如何取消AJAX请求的演示 -如果在预定义的等待时间内没有从服务器返回数据。
HTML:
<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 reload xhr.abort();