使用jQuery,如何取消/中止尚未收到响应的Ajax请求?
ajaxStop
仅在所有AJAX请求完成时才检测,它不会停止请求。以我的经验,您会像这样使用它:$(document).ajaxStop(function(){alert("All done")})
。使用.abort()
是最好的选择。
使用jQuery,如何取消/中止尚未收到响应的Ajax请求?
ajaxStop
仅在所有AJAX请求完成时才检测,它不会停止请求。以我的经验,您会像这样使用它:$(document).ajaxStop(function(){alert("All done")})
。使用.abort()
是最好的选择。
Answers:
大多数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 request
xhr.abort()
更新: 从jQuery 1.5开始,返回的对象是名为jqXHR的本机XMLHttpRequest对象的包装。该对象似乎公开了所有本机属性和方法,因此上面的示例仍然有效。请参阅jqXHR对象(jQuery API文档)。
更新2:
从jQuery 3开始,ajax方法现在返回带有其他方法的promise(例如abort),因此上面的代码仍然有效,尽管返回的对象不再可用xhr
。在此处查看3.0博客。
更新3:xhr.abort()
仍然适用于jQuery3.x。不要以为更新2是正确的。有关jQuery Github存储库的更多信息。
abort
它没有关闭与服务器的已建立连接,因此success
仍会被调用。这对于使用长轮询的Comet实现非常有问题。
这是一个异步请求,这意味着一旦它被发送出去。
如果您的服务器由于AJAX请求而开始进行非常昂贵的操作,则您最好的办法是打开服务器以侦听取消请求,然后发送单独的AJAX请求以通知服务器停止其正在执行的操作。
否则,只需忽略AJAX响应。
AJAX请求可能无法按启动顺序完成。除了放弃最近的响应之外,您还可以选择忽略所有AJAX响应:
代码粗略概述:
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
我们只需要解决此问题并测试了三种不同的方法。
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是否保证调用.complete()方法,这可能会导致死锁。在我们的测试中,我们无法重现这种情况。
最好总是这样做。
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,那就更好了。
只需致电xhr。abort()是jquery ajax对象还是本机XMLHTTPRequest对象。
例:
//jQuery ajax
$(document).ready(function(){
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);
我正在做一个实时搜索解决方案,需要取消可能花费比最新/最新请求更长的请求。
就我而言,我使用的是这样的:
//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
正如线程上的许多人所指出的那样,仅因为请求在客户端中止,服务器仍将处理该请求。这会在服务器上造成不必要的负载,因为它正在做我们不希望在前端监听的工作。
我试图解决的问题(其他人也可能会遇到此问题)是,当用户在输入字段中输入信息时,我想触发对Google即搜即得类型的请求。
为了避免触发不必要的请求并保持前端的简洁性,我执行了以下操作:
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毫秒发送一个请求(您可以根据自己的需要自定义一个变量)。如果您在理解这里到底发生了什么时遇到麻烦,请在if块之前登录xhrCount
并登录xhrQueue
到控制台。
只需使用ajax.abort()例如,您可以在发送另一个这样的请求之前中止任何待处理的ajax请求
//check for existing ajax request
if(ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
您可以使用此方法中止任何连续的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 POST
url: "index.php",
data: {'id':id},
success: function () {
},
beforeSend: function () {
if (request !== null) {
request.abort();
}
}
});
});
</script>
以下代码显示了启动和中止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);
});
$.ajaxStop
吗?