使用 jQuery 中止 Ajax 请求
Posted
技术标签:
【中文标题】使用 jQuery 中止 Ajax 请求【英文标题】:Abort Ajax requests using jQuery 【发布时间】:2010-10-01 14:07:17 【问题描述】:是否有可能使用 jQuery,我取消/中止了我尚未收到响应的 Ajax 请求?
【问题讨论】:
也许我误解了这个问题,但你不能简单地使用$.ajaxStop
吗?
@LukeMadhanga;我认为ajaxStop
仅检测所有 AJAX 请求何时完成,它不会停止请求。根据我的经验,您会像这样使用它:$(document).ajaxStop(function()alert("All done"))
。使用.abort()
是最好的选择。
【参考方案1】:
大多数 jQuery Ajax 方法返回一个 XMLHttpRequest(或等效的)对象,因此您可以使用 abort()
。
查看文档:
abort Method (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 开始,返回的对象是原生 XMLHttpRequest 对象的包装器,称为 jqXHR。这个对象似乎暴露了所有的本地属性和方法,所以上面的例子仍然有效。请参阅The jqXHR Object(jQuery API 文档)。
更新 2:
从 jQuery 3 开始,ajax 方法现在返回一个带有额外方法(如 abort)的 promise,因此上面的代码仍然有效,尽管返回的对象不再是 xhr
。请参阅3.0 blog here。
更新 3:xhr.abort()
仍然适用于 jQuery 3.x。不要假设 update 2 是正确的。 More info on jQuery Github repository.
【讨论】:
【参考方案2】:您无法撤回请求,但您可以设置超时值,在此之后响应将被忽略。有关 jquery AJAX 选项,请参阅此 page。我相信如果超过超时期限,您的错误回调将被调用。每个 AJAX 请求已经有一个默认超时。
您也可以在请求对象上使用abort() 方法,但是虽然它会导致客户端停止侦听事件,但它可能可能不会阻止服务器处理它。
【讨论】:
【参考方案3】:这是一个 asynchronous
请求,这意味着一旦发送,它就在外面。
如果您的服务器由于AJAX
请求而启动了一个非常昂贵的操作,您可以做的最好的事情是打开您的服务器以侦听取消请求,并发送单独的AJAX
请求通知服务器停止任何操作它正在做。
否则,只需忽略 AJAX
响应。
【讨论】:
在这种情况下,异步只是意味着请求不会中断脚本的流程。浏览器现在可以在请求完成之前提前中止请求。【参考方案4】:将您进行的调用保存在一个数组中,然后对每个调用调用 xhr.abort()。
巨大的警告:您可以中止请求,但这只是客户端。服务器端可能仍在处理请求。如果您将 PHP 或 ASP 之类的东西用于会话数据,则会话数据将被锁定,直到 ajax 完成。因此,要让用户继续浏览网站,您必须调用 session_write_close()。这将保存会话并将其解锁,以便其他等待继续的页面将继续。如果没有这个,可能会有多个页面等待解除锁定。
【讨论】:
【参考方案5】: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
Demo on jsFiddle
【讨论】:
【参考方案6】:我们只需要解决这个问题并测试了三种不同的方法。
-
确实按照@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() 方法,这可能会产生死锁情况。在我们的测试中,我们无法重现这种情况。
【讨论】:
【参考方案7】:做这样的事情。
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会更好。
【讨论】:
我还检查请求是否已经在运行,但我使用布尔值,因为它更轻。 ` var $request; if ($request != null)` 为什么?这里的代码是创建一个空变量,然后在没有任何严格检查的情况下检查它是否不为空。这个无用的检查总是错误的有什么教育意义?此外,这是一个较晚的答案,它只是告诉使用abort()
(上面已经回答),但没有以任何方式解释它。 “做这样的事情总是最好的做法”这句话只是一个积极的流行语,诱使没有经验的人投票。在澄清或改进之前投反对票。
我试图删除流行语“它始终是最佳实践”,因为它不是中立的,它只是分散注意力,而且从我的 POV 来看不是真的,没有进一步的说明。【参考方案8】:
只需调用 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);
【讨论】:
【参考方案9】:正如线程中的许多人所指出的那样,仅仅因为请求在客户端被中止,服务器仍将处理该请求。这会在服务器上造成不必要的负载,因为它正在做我们已经停止在前端收听的工作。
我试图解决的问题(其他人也可能遇到)是,当用户在输入字段中输入信息时,我想触发对 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
记录到控制台。
【讨论】:
【参考方案10】:你可以使用这个来中止任何连续的 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>
【讨论】:
【参考方案11】:我正在做一个实时搜索解决方案,需要取消可能比最新/最新请求花费更长的时间的待处理请求。
在我的例子中,我使用了这样的东西:
//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
【讨论】:
【参考方案12】:只需使用 ajax.abort() 例如,您可以在发送另一个这样的 ajax 请求之前中止任何待处理的 ajax 请求
//check for existing ajax request
if(ajax)
ajax.abort();
//then you make another ajax request
$.ajax(
//your code here
);
【讨论】:
【参考方案13】:没有可靠的方法可以做到这一点,一旦请求在进行中,我什至不会尝试;做出合理反应的唯一方法是忽略响应。
在大多数情况下,它可能发生在以下情况下:用户过于频繁地点击按钮触发了许多连续的 XHR,在这里你有很多选择,要么阻止按钮直到 XHR 返回,或者甚至不触发新的 XHR 而另一个正在运行提示用户向后倾斜 - 或丢弃任何未决的 XHR 响应,但最近的。
【讨论】:
【参考方案14】:以下代码显示了启动和中止 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!" >
【讨论】:
请解释这是如何解决问题的。这将有助于 OP 和其他未来的搜索者。【参考方案15】:我遇到了轮询问题,一旦页面关闭,轮询就会继续,所以在我的原因中,用户会错过更新,因为在页面关闭后的接下来 50 秒内设置了 mysql 值,即使我杀死了 ajax请求,我想通了,使用 $_SESSION 设置一个 var 不会在轮询中更新其自身,直到它结束并且一个新的已经开始,所以我所做的是在我的数据库中设置一个值 0 = offpage ,而我正在轮询我查询该行并返回 false;当它为 0 时,轮询中的查询显然会为您提供当前值...
希望对你有帮助
【讨论】:
【参考方案16】:如果xhr.abort();
导致页面重新加载,
那么你可以在abort之前设置onreadystatechange
来防止:
// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();
【讨论】:
【参考方案17】:我分享了一个 demo,它演示了如何取消 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,...
。【参考方案18】:
这是我基于上面许多答案的实现:
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;
);
【讨论】:
以上是关于使用 jQuery 中止 Ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章