简体   繁体   English

使用 jQuery 中止 Ajax 请求

[英]Abort Ajax requests using jQuery

是否有可能使用 jQuery取消/中止我尚未收到响应的 Ajax 请求

Most of the jQuery Ajax methods return an XMLHttpRequest (or the equivalent) object, so you can just use abort() .大多数 jQuery Ajax 方法都返回一个 XMLHttpRequest(或等效的)对象,因此您可以只使用abort()

See the documentation:请参阅文档:

  • abort Method ( MSDN ). 中止方法( MSDN )。 Cancels the current HTTP request.取消当前的 HTTP 请求。
  • abort() ( MDN ). abort() ( MDN )。 If the request has been sent already, this method will abort the request.如果请求已经发送,此方法将中止请求。
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()

UPDATE: As of jQuery 1.5 the returned object is a wrapper for the native XMLHttpRequest object called jqXHR.更新:从 jQuery 1.5 开始,返回的对象是名为 jqXHR 的原生 XMLHttpRequest 对象的包装器。 This object appears to expose all of the native properties and methods so the above example still works.该对象似乎公开了所有本机属性和方法,因此上面的示例仍然有效。 See The jqXHR Object (jQuery API documentation).请参阅jqXHR 对象(jQuery API 文档)。

UPDATE 2: As of jQuery 3, the ajax method now returns a promise with extra methods (like abort), so the above code still works, though the object being returned is not an xhr any more.更新 2:从 jQuery 3 开始,ajax 方法现在返回一个带有额外方法(如 abort)的承诺,因此上面的代码仍然有效,尽管返回的对象不再是xhr See the 3.0 blog here .请参阅此处3.0 博客

UPDATE 3 : xhr.abort() still works on jQuery 3.x.更新 3xhr.abort()仍然适用于 jQuery 3.x。 Don't assume the update 2 is correct.不要假设更新 2是正确的。 More info on jQuery Github repository . 有关 jQuery Github 存储库的更多信息

You can't recall the request but you can set a timeout value after which the response will be ignored.您无法撤回请求,但您可以设置超时值,超时后响应将被忽略。 See this page for jquery AJAX options.有关 jquery AJAX 选项,请参阅此页面 I believe that your error callback will be called if the timeout period is exceeded.我相信如果超过超时时间,您的错误回调将被调用。 There is already a default timeout on every AJAX request.每个 AJAX 请求已经有一个默认超时。

You can also use theabort() method on the request object but, while it will cause the client to stop listening for the event, it may probably will not stop the server from processing it.您还可以在请求对象上使用abort()方法,但是,虽然它会导致客户端停止侦听事件,但它 可能 不会阻止服务器处理它。

It's an asynchronous request, meaning once it's sent it's out there.这是一个asynchronous请求,这意味着一旦它被发送出去。

In case your server is starting a very expensive operation due to the AJAX request, the best you can do is open your server to listen for cancel requests, and send a separate AJAX request notifying the server to stop whatever it's doing.如果您的服务器由于AJAX请求而开始执行非常昂贵的操作,您能做的最好的事情就是打开服务器以侦听取消请求,然后发送一个单独的AJAX请求,通知服务器停止正在执行的任何操作。

Otherwise, simply ignore the AJAX response.否则,只需忽略AJAX响应。

Save the calls you make in an array, then call xhr.abort() on each.将您所做的调用保存在一个数组中,然后在每个调用上调用 xhr.abort()。

HUGE CAVEAT: You can abort a request, but that's only the client side.巨大的警告:您可以中止请求,但这只是客户端。 The server side could still be processing the request.服务器端可能仍在处理请求。 If you are using something like PHP or ASP with session data, the session data is locked until the ajax has finished.如果您使用 PHP 或 ASP 之类的东西来处理会话数据,则会话数据将被锁定,直到 ajax 完成。 So, to allow the user to continue browsing the website, you have to call session_write_close ().所以,为了让用户继续浏览网站,你必须调用session_write_close ()。 This saves the session and unlocks it so that other pages waiting to continue will proceed.这将保存会话并解锁它,以便其他等待继续的页面将继续进行。 Without this, several pages can be waiting for the lock to be removed.如果没有这个,几个页面可能会等待锁定被删除。

AJAX requests may not complete in the order they were started. AJAX 请求可能不会按照它们开始的顺序完成。 Instead of aborting, you can choose to ignore all AJAX responses except for the most recent one:除了中止之外,您可以选择忽略所有 AJAX 响应,而不是中止:

  • Create a counter创建一个计数器
  • Increment the counter when you initiate AJAX request发起 AJAX 请求时增加计数器
  • Use the current value of counter to "stamp" the request使用计数器的当前值来“标记”请求
  • In the success callback compare the stamp with the counter to check if it was the most recent request在成功回调中,将时间戳与计数器进行比较以检查它是否是最近的请求

Rough outline of code:粗略的代码概要:

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 jsFiddle 上的演示

We just had to work around this problem and tested three different approaches.我们只需要解决这个问题并测试了三种不同的方法。

  1. does cancel the request as suggested by @meouw确实按照@meouw 的建议取消了请求
  2. execute all request but only processes the result of the last submit执行所有请求但只处理上次提交的结果
  3. prevents new requests as long as another one is still pending只要另一个请求仍在等待中,就阻止新请求

 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" />

In our case we decided to use approach #3 as it produces less load for the server.在我们的例子中,我们决定使用方法 #3,因为它为服务器产生的负载更少。 But I am not 100% sure if jQuery guarantees the call of the .complete()-method, this could produce a deadlock situation.但我不是 100% 确定 jQuery 是否保证 .complete() 方法的调用,这可能会产生死锁情况。 In our tests we could not reproduce such a situation.在我们的测试中,我们无法重现这种情况。

It is always best practice to do something like this.做这样的事情总是最好的做法。

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);
    });

But it is much better if you check an if statement to check whether the ajax request is null or not.但是如果你检查一个 if 语句来检查 ajax 请求是否为空,那就更好了。

meouw的解决方案是正确的,但是如果您对更多控制感兴趣,则可以尝试jQuery的Ajax Manager插件

Just call xhr.只需调用 xhr。 abort() whether it's jquery ajax object or native XMLHTTPRequest object. abort()无论是 jquery ajax 对象还是原生 XMLHTTPRequest 对象。

example:例子:

//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);

As many people on the thread have noted, just because the request is aborted on the client-side, the server will still process the request.正如该线程中的许多人所指出的那样,仅仅因为请求在客户端中止,服务器仍将处理该请求。 This creates unnecessary load on the server because it's doing work that we've quit listening to on the front-end.这会在服务器上造成不必要的负载,因为它正在执行我们已经停止在前端侦听的工作。

The problem I was trying to solve (that others may run in to as well) is that when the user entered information in an input field, I wanted to fire off a request for a Google Instant type of feel.我试图解决的问题(其他人也可能遇到)是,当用户在输入字段中输入信息时,我想触发对 Google Instant 类型感觉的请求。

To avoid firing unnecessary requests and to maintain the snappiness of the front-end, I did the following:为了避免触发不必要的请求并保持前端的敏捷性,我执行了以下操作:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

This will essentially send one request every 150ms (a variable that you can customize for your own needs).这基本上每 150 毫秒发送一个请求(您可以根据自己的需要自定义一个变量)。 If you're having trouble understanding what exactly is happening here, log xhrCount and xhrQueue to the console just before the if block.如果您无法理解此处究竟发生了什么,请在 if 块之前将xhrCountxhrQueue到控制台。

You can abort any continuous ajax call by using this您可以使用此中止任何连续的 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>

I was doing a live search solution and needed to cancel pending requests that may have taken longer than the latest/most current request.我正在做一个实时搜索解决方案,需要取消可能比最新/最新请求花费的时间更长的待处理请求。

In my case I used something like this:在我的情况下,我使用了这样的东西:

//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 

Just use ajax.abort() for example you could abort any pending ajax request before sending another one like this只需使用 ajax.abort() 例如,您可以在发送另一个这样的请求之前中止任何挂起的 ajax 请求

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

there is no reliable way to do it, and I would not even try it, once the request is on the go;没有可靠的方法来做到这一点,一旦请求在路上,我什至不会尝试; the only way to react reasonably is to ignore the response.做出合理反应的唯一方法是忽略响应。

in most cases, it may happen in situations like: a user clicks too often on a button triggering many consecutive XHR, here you have many options, either block the button till XHR is returned, or dont even trigger new XHR while another is running hinting the user to lean back - or discard any pending XHR response but the recent.在大多数情况下,它可能发生在以下情况:用户过于频繁地点击一个按钮触发了许多连续的 XHR,在这里你有很多选择,要么阻止按钮直到 XHR 返回,或者在另一个正在运行提示时甚至不触发新的 XHR用户向后靠 - 或丢弃任何未决的 XHR 响应,但最近的响应。

The following code shows initiating as well as aborting an Ajax request:以下代码显示了启动和中止 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!" >

I had the problem of polling and once the page was closed the poll continued so in my cause a user would miss an update as a mysql value was being set for the next 50 seconds after page closing, even though I killed the ajax request, I figured away around, using $_SESSION to set a var won't update in the poll its self until its ended and a new one has started, so what I did was set a value in my database as 0 = offpage , while I'm polling I query that row and return false;我遇到了轮询问题,一旦页面关闭,轮询会继续进行,因此在我的原因中,用户会错过更新,因为在页面关闭后的接下来 50 秒内设置了 mysql 值,即使我杀死了 ajax 请求,我想通了,使用 $_SESSION 设置一个 var 不会在轮询中更新它自己直到它结束并且一个新的已经开始,所以我所做的是在我的数据库中设置一个值 0 = offpage ,而我轮询我查询该行并返回false; when it's 0 as querying in polling will get you current values obviously...当它为 0 时,在轮询中查询显然会得到你当前的值......

I hope this helped我希望这有帮助

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

Then you can set onreadystatechange before abort to prevent:然后您可以在中止之前设置onreadystatechange以防止:

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

I have shared a demo that demonstrates how to cancel an AJAX request-- if data is not returned from the server within a predefined wait time.我分享了一个演示,它演示了如何取消 AJAX 请求——如果在预定义的等待时间内没有从服务器返回数据。

HTML : HTML :

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

JS CODE: 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);   
});

This is my implementation based on many answers above:这是我基于上述许多答案的实现:

  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;
          }          
        }); 
  } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM