提问人:lukewm 提问时间:1/15/2009 最后编辑:Always Helpinglukewm 更新时间:3/18/2022 访问量:705087
使用 jQuery 中止 Ajax 请求
Abort Ajax requests using jQuery
答:
您无法调用请求,但可以设置一个超时值,超过该值后将忽略响应。有关 jquery AJAX 选项,请参阅此页面。我相信如果超过超时期限,将调用您的错误回调。每个 AJAX 请求都已存在默认超时。
您也可以在请求对象上使用 abort() 方法,但是,虽然它会导致客户端停止侦听事件,但它可能不会阻止服务器处理它。
这是一个异步
请求,这意味着一旦发送,它就在那里。
如果您的服务器由于请求而启动了非常昂贵的操作,您能做的最好的事情就是打开服务器以侦听取消请求,并发送单独的请求,通知服务器停止它正在执行的任何操作。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 request
xhr.abort()
更新:从 jQuery 1.5 开始,返回的对象是名为 jqXHR 的本机 XMLHttpRequest 对象的包装器。此对象似乎公开了所有本机属性和方法,因此上面的示例仍然有效。请参阅 jqXHR 对象(jQuery API 文档)。
更新2:从 jQuery 3 开始,ajax 方法现在返回一个带有额外方法(如 abort)的 promise,因此上面的代码仍然有效,尽管返回的对象不再是 a。请参阅此处的 3.0 博客。xhr
更新 3:仍然适用于 jQuery 3.x。不要假设更新 2 是正确的。有关 jQuery Github 存储库的更多信息。xhr.abort()
将您发出的呼叫保存在阵列中,然后对每个呼叫进行呼叫。xhr.abort()
需要注意的是:您可以中止请求,但这只是客户端。服务器端可能仍在处理请求。如果将 PHP 或 ASP 之类的东西用于会话数据,则会话数据将被锁定,直到 ajax 完成。因此,要允许用户继续浏览网站,您必须调用 session_write_close()。
这将保存会话并解锁它,以便等待继续的其他页面将继续。如果没有这个,可能会有多个页面等待锁定被移除。
我们只需要解决这个问题,并测试了三种不同的方法。
- 按照@meouw的建议取消请求
- 执行所有请求,但只处理上次提交的结果
- 只要另一个请求仍处于待处理状态,就会阻止新请求
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() 方法,这可能会产生死锁情况。在我们的测试中,我们无法重现这种情况。
我遇到了轮询问题,一旦页面关闭,轮询就会继续,所以在我的原因中,用户会错过更新,因为在页面关闭后的下一个 50 秒内设置了 mysql 值,即使我杀死了 ajax 请求,我想通了,使用 $_SESSION 来设置 var 不会在轮询中自行更新,直到它结束并且一个新的开始, 所以我所做的是在我的数据库中设置一个值为 0 = offpage ,当我轮询时,我查询该行并返回 false;当它为 0 时,因为在轮询中查询显然会获得当前值......
我希望这会有所帮助
例如,只需使用 ajax.abort(),您就可以在发送另一个这样的请求之前中止任何待处理的 ajax 请求
//check for existing ajax request
if(ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
我正在做一个实时搜索解决方案,需要取消可能比最新/最新请求花费更长时间的待处理请求。
就我而言,我使用了这样的东西:
//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
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
正如线程上的许多人所指出的那样,仅仅因为请求在客户端中止,服务器仍将处理该请求。这会在服务器上造成不必要的负载,因为它正在执行我们在前端停止侦听的工作。
我试图解决的问题(其他人也可能会遇到)是,当用户在输入字段中输入信息时,我想发出一个请求,以获得 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);
});
这基本上每 150 毫秒发送一个请求(您可以根据自己的需要自定义一个变量)。如果您无法理解这里到底发生了什么,请在 if 块之前登录并登录到控制台。xhrCount
xhrQueue
做这样的事情始终是最佳做法。
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,那就更好了。
评论
abort()
只需致电 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);
没有可靠的方法可以做到这一点,一旦请求在旅途中,我什至不会尝试;做出合理反应的唯一方法是忽略响应。
在大多数情况下,它可能发生在以下情况下:用户过于频繁地点击触发多个连续 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!" >
评论
我分享了一个演示,演示了如何在预定义的等待时间内从服务器返回数据时取消 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);
});
评论
$.ajax
提供了一个选项,因此您无需编写自己的选项。只需使用 .timeout
..., data: {...}, timeout: waitTime,...
如果导致页面重新加载,xhr.abort();
然后,您可以设置“中止前”以防止:onreadystatechange
// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.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 POST
url: "index.php",
data: {'id':id},
success: function () {
},
beforeSend: function () {
if (request !== null) {
request.abort();
}
}
});
});
</script>
这是我基于上述许多答案的实现:
var activeRequest = false; //global var
var filters = {...};
apply_filters(filters);
//function triggering the ajax request
function apply_filters(filters){
//prepare data and other functionalities
var data = {};
//limit the ajax calls
if (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 false
activeRequest = 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;
}
});
}
评论
$.ajaxStop
ajaxStop
$(document).ajaxStop(function(){alert("All done")})
.abort()