使用 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。

更新 3xhr.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 块之前将 xhrCountxhrQueue 记录到控制台。

【讨论】:

【参考方案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 请求的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery 中止待处理/积压的 AJAX 请求

使用 jQuery 中止 JSONP ajax 请求

如何取消/中止 jQuery AJAX 请求?

jQuery 中止请求

错误:“CSRF 验证失败。请求中止。”在 Django 中使用 jquery ajax 时

jQuery UI 自动完成:中止请求