使用jQuery中止Ajax请求

luk*_*ewm 1775 javascript ajax jquery

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

meo*_*ouw 1702

大多数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()
Run Code Online (Sandbox Code Playgroud)

更新: 从jQuery 1.5开始,返回的对象是原生XMLHttpRequest对象的包装器,名为jqXHR.此对象似乎显示所有本机属性和方法,因此上述示例仍然有效.请参阅jqXHR对象(jQuery API文档).

更新2: 从jQuery 3开始,ajax方法现在返回一个带有额外方法(如abort)的promise,所以上面的代码仍然有效,尽管返回的对象不再存在xhr.请参阅此处3.0博客.

更新3:xhr.abort()仍然适用于jQuery 3.x. 不要认为更新2是正确的.有关jQuery Github存储库的更多信息.

  • @brad不幸的是,`abort`没有关闭与服务器建立的连接,所以仍然会调用`success`.对于具有长轮询的Comet的实现,这是非常有问题的. (64认同)
  • 这就像点击浏览器上的"停止"按钮一样.它取消了请求.然后,您可以将同一个XHR对象重用于另一个请求. (12认同)
  • `.abort()`在jQuery 3.2.1中仍适用于我.jQuery核心团队成员的这个[相关github问题中的评论](https://github.com/jquery/jquery/issues/2084#issuecomment-308173243)似乎暗示这个答案是不正确的并且`.abort( )`没有删除. (9认同)
  • 在我的测试中,请求在浏览器中止,但是.fail()方法是使用jqXHR,status = 0和jqXHR,statusMessage ="abort"调用的. (8认同)
  • @ErvWalter您可以发送另一个取消前一个请求的请求. (6认同)
  • 它将不再适用于jQuery 3.0 http://blog.jquery.com/2016/01/14/jquery-3-0-beta-released/ (6认同)
  • @JoeCoderGuy:我不相信.服务器仍然会这样做,但在我的测试中(至少在Chrome v23中),不会调用javascript成功方法. (3认同)
  • 你能详细说明abort()究竟是做什么的吗? (2认同)
  • @ user420667我必须有一个奇怪的版本,因为它不取消我的(相同的版本).我确实看到另一个问题,在localhost上这样做可能没有足够的时间来取消http://stackoverflow.com/questions/8584402/jquery-ajax-abort-browser-still-receives-the-data (2认同)
  • 对于nodejs,调用`req.on('close',function(){})`以检测javascript端是否调用了`.abort()` (2认同)
  • 在某些情况下,我观​​察到按下并按住退出按钮会取消AJAX请求. (2认同)
  • 给`AjaxHelper`错误:**。abort()**不是一个函数 (2认同)

tva*_*son 113

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

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


Yuv*_*dam 73

这是一个异步请求,这意味着一旦它被发送到那里.

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

否则,只需忽略AJAX响应.

  • 在这种情况下,异步只是意味着请求不会中断脚本的流程.浏览器现在能够在请求完成之前提前中止请求. (47认同)
  • 我们如何向服务器发送取消请求?我不明白服务器如何知道停止处理哪个请求?你举个例子吗?谢谢. (4认同)
  • @Kloar,如果服务器尚未收到请求(f.ex.大型多部分请求),客户端可能会关闭套接字,服务器也会受到影响. (4认同)
  • PHP会自动检查中止的请求,并自动终止.见http://php.net/manual/en/function.ignore-user-abort.php (4认同)
  • @LuckySoni,Elephanthunter只讨论客户端.服务器不受.abort请求的影响 (3认同)

Tei*_*Tei 67

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

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


Sal*_*n A 56

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
Run Code Online (Sandbox Code Playgroud)

演示jsFiddle


oyo*_*ant 41

我们只需要解决这个问题并测试三种不同的方法.

  1. 确实取消了@meouw建议的请求
  2. 执行所有请求但仅处理上次提交的结果
  3. 只要另一个请求仍处于待处理状态,就会阻止新请求

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();
  });
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />
Run Code Online (Sandbox Code Playgroud)

在我们的例子中,我们决定使用方法#3,因为它减少了服务器的负载.但我不是100%肯定,如果jQuery保证调用.complete() - 方法,这可能会产生死锁情况.在我们的测试中,我们无法重现这种情况.


Tha*_*ara 36

做这样的事情总是最好的做法.

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);
    });
Run Code Online (Sandbox Code Playgroud)

但是,如果检查if语句以检查ajax请求是否为null,则会好得多.

  • 我还检查一个请求是否已经在运行,但我使用了一个布尔值,因为它更轻. (2认同)

cui*_*ing 15

只需拨打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);
Run Code Online (Sandbox Code Playgroud)


小智 13

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

就我而言,我使用了这样的东西:

//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 
Run Code Online (Sandbox Code Playgroud)


bri*_*hea 12

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

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

});
Run Code Online (Sandbox Code Playgroud)

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


小智 11

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

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


com*_*ome 10

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

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


Sou*_*rik 9

您可以使用此方法中止任何连续的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>
Run Code Online (Sandbox Code Playgroud)


zlo*_*ctb 7

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


 })
Run Code Online (Sandbox Code Playgroud)
<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!" >
Run Code Online (Sandbox Code Playgroud)

  • 请解释这是如何解决这个问题的.这将有助于OP和其他未来的搜索者. (5认同)

vik*_*kyd 6

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

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

// ? prevent page reload by abort()
xhr.onreadystatechange = null;
// ? may cause page reload
xhr.abort();
Run Code Online (Sandbox Code Playgroud)


小智 5

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

我希望这有帮助


gan*_*esh 5

我分享了一个演示,它演示了如何取消 AJAX 请求——如果在预定义的等待时间内没有从服务器返回数据。

HTML :

<div id="info"></div>
Run Code Online (Sandbox Code Playgroud)

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);   
});
Run Code Online (Sandbox Code Playgroud)

  • [`$.ajax`](http://api.jquery.com/jquery.ajax/) 提供了一个 `timeout` 选项,因此您不需要编写自己的选项。只需使用 `..., data: {...}, timeout: waitTime,...`。 (2认同)