使用jQuery中止Ajax请求

时间:2009-01-15 12:45:19

标签: javascript jquery ajax

使用jQuery,我如何取消/中止Ajax请求我尚未收到响应?

19 个答案:

答案 0 :(得分:1676)

大多数jQuery Ajax方法返回XMLHttpRequest(或等效的)对象,因此您只需使用abort()

参见文档:

  • abort MethodMSDN)。取消当前的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开始,返回的对象是名为jqXHR的本机XMLHttpRequest对象的包装器。此对象似乎显示所有本机属性和方法,因此上述示例仍然有效。请参阅 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

答案 1 :(得分:111)

您无法调用请求,但可以设置超时值,之后将忽略响应。有关jquery AJAX选项,请参阅此page。我相信如果超过超时时间,将调用您的错误回调。每个AJAX请求都有一个默认超时。

您也可以在请求对象上使用abort()方法,但是,虽然它会导致客户端停止侦听事件,但可能可能不会阻止服务器处理它

答案 2 :(得分:72)

这是一个异步请求,这意味着一旦将其发送到那里就会出现。

如果您的服务器由于AJAX请求而开始执行非常昂贵的操作,您可以做的最好的事情是打开服务器以侦听取消请求,并发送单独的AJAX请求,通知服务器停止正在执行的操作。< / p>

否则,只需忽略AJAX响应。

答案 3 :(得分:65)

保存您在数组中进行的调用,然后在每个调用上调用xhr.abort()。

巨大的洞穴:您可以中止请求,但这只是客户端。服务器端仍然可以处理请求。如果您使用PHP或ASP等会话数据,会话数据将被锁定,直到ajax完成。因此,要允许用户继续浏览网站,您必须调用 session_write_close ()。这将保存会话并解锁,以便其他页面等待继续。没有这个,几个页面可以等待删除锁。

答案 4 :(得分:53)

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

Demo on jsFiddle

答案 5 :(得分:39)

我们不得不解决这个问题并测试了三种不同的方法。

  1. 确实取消了@meouw
  2. 建议的请求
  3. 执行所有请求但仅处理上次提交的结果
  4. 只要另一个请求仍处于待处理状态,
  5. 就会阻止新请求
  6. 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() - 方法,这可能会产生死锁情况。在我们的测试中,我们无法重现这种情况。

答案 6 :(得分:34)

最好这样做。

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,则会好得多。

答案 7 :(得分:20)

meouw's solution是正确的,但如果您对更多控制感兴趣,那么您可以尝试使用Ajax Manager plugin进行jQuery。

答案 8 :(得分:13)

只需调用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 :(得分:12)

我正在进行实时搜索解决方案,需要取消可能比最新/最新请求更长的待处理请求。

在我的情况下,我使用了这样的东西:

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

答案 10 :(得分:11)

正如线程上的许多人所指出的那样,仅仅因为请求在客户端被中止,服务器仍然会处理请求。这会在服务器上产生不必要的负载,因为它正在做我们已经停止在前端监听的工作。

我试图解决的问题(其他人可能会遇到的问题)是,当用户在输入字段中输入信息时,我想发出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);

});

这实际上每150ms发送一个请求(一个可以根据自己的需要自定义的变量)。如果您无法理解这里到底发生了什么,请在if块之前将xhrCountxhrQueue记录到控制台。

答案 11 :(得分:10)

只需使用ajax.abort(),例如你可以在发送另一个这样的ajax请求之前中止

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

答案 12 :(得分:9)

没有可靠的方法可以做到这一点,一旦请求在旅途中,我甚至都不会尝试; 唯一合理反应的方式是忽略响应。

在大多数情况下,它可能发生在以下情况:用户经常点击触发多个连续XHR的按钮,这里有很多选项,要么阻止按钮直到XHR返回,要么甚至不触发新的XHR而另一个正在运行暗示用户向后倾斜 - 或丢弃任何待处理的XHR响应,但是最近的。

答案 13 :(得分:7)

您可以使用此

中止任何连续的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>

答案 14 :(得分:6)

以下代码显示了启动和中止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!" >

答案 15 :(得分:5)

我遇到了轮询的问题,一旦页面关闭,民意调查就会继续进行,因此在我的原因中,用户会错过更新,因为在页面关闭后的下一个50秒内设置了mysql值,即使我杀死了ajax请求,我想了一下,使用$ _SESSION来设置var将不会在轮询中自动更新直到它结束并且新的一个已经开始,所以我所做的是在我的数据库中设置一个值0 = offpage,而我正在轮询我查询该行并返回false;当它为0时,在轮询中查询会明显地获得当前值......

我希望这有帮助

答案 16 :(得分:3)

我已经共享了一个demo来演示如何取消AJAX请求 - 如果在预定义的等待时间内没有从服务器返回数据。

HTML:

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

JS CODE:

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

答案 17 :(得分:3)

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

然后您可以在中止之前设置onreadystatechange以防止:

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

答案 18 :(得分:1)

这是我基于上述许多答案的实现:

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