使用jQuery中止Ajax请求


1827

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


2
也许我误解了这个问题,但是您不能简单地使用它$.ajaxStop吗?
卢克·麦德加

17
@LukeMadhanga; 我认为ajaxStop仅在所有AJAX请求完成时才检测,它不会停止请求。以我的经验,您会像这样使用它:$(document).ajaxStop(function(){alert("All done")})。使用.abort()是最好的选择。
TheCarver 2013年

Answers:


1743

大多数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()

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

更新2: 从jQuery 3开始,ajax方法现在返回带有其他方法的promise(例如abort),因此上面的代码仍然有效,尽管返回的对象不再可用xhr。在此处查看3.0博客

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


12
这就像单击浏览器上的“停止”按钮。取消请求。然后,您可以将同一XHR对象重用于另一个请求。
meouw

65
@brad不幸的是,abort它没有关闭与服务器的已建立连接,因此success仍会被调用。这对于使用长轮询的Comet实现非常有问题。
pepkin88 2011年

6
@ErvWalter您可以调度另一个请求,以取消上一个请求。
Asad Saeeduddin

8
在我的测试中,该请求在浏览器中被中止,但是.fail()方法是使用jqXHR,status = 0和jqXHR,statusMessage =“ abort”调用的
BJ Safdie

9
.abort()在jQuery 3.2.1中仍然适用于我。jQuery核心团队成员在相关github问题中的评论似乎暗示该答案不正确,.abort() 并且未删除。
alarive

117

您无法撤回该请求,但可以设置一个超时值,在此之后将忽略响应。请参阅此页面以获取jquery AJAX选项。我相信如果超过超时期限,就会调用您的错误回调。每个AJAX请求都已经存在默认超时。

您还可以在请求对象上使用abort()方法,但是,尽管这将导致客户端停止监听事件,但可能不会阻止服务器对其进行处理。


74

这是一个异步请求,这意味着一旦它被发送出去。

如果您的服务器由于AJAX请求而开始进行非常昂贵的操作,则您最好的办法是打开服务器以侦听取消请求,然后发送单独的AJAX请求以通知服务器停止其正在执行的操作。

否则,只需忽略AJAX响应。


48
在这种情况下,异步只是意味着请求不会中断脚本的流程。现在,浏览器可以在请求完成之前过早中止请求。
ElephantHunter 2012年

4
我们如何向服务器发送取消请求?我不明白服务器如何知道停止处理哪个请求?你能举个例子吗?谢谢。
幸运Soni 2014年

3
@ LuckySoni,Elephanthunter仅在讨论客户端。该服务器将不受.abort请求的影响
Kloar 2014年

4
@Kloar,如果服务器尚未收到该请求(例如,大型多重请求),则客户端可能会关闭套接字,并且服务器将受到影响。
白色,

4
PHP自动检查中止的请求,并自动终止。参见php.net/manual/en/function.ignore-user-abort.php
hanshenrik 2015年

68

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

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


由于您总是取消前一个,难道您不总是这样做吗?(无需使用数组)
极性

60

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

jsFiddle上的演示


由于取消XHR请求的警告(请参阅此页面上的其他评论),这可能是最好和最简单的选择。
Quinn Comendant

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();
  });
})
<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()方法,这可能会导致死锁。在我们的测试中,我们无法重现这种情况。


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

但是,如果检查一条if语句来检查ajax请求是否为null,那就更好了。


2
我还检查请求是否已在运行,但我使用布尔值,因为它比较轻。
请点击这里

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

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 

12

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

我试图解决的问题(其他人也可能会遇到此问题)是,当用户在输入字段中输入信息时,我想触发对Google即搜即得类型的请求。

为了避免触发不必要的请求并保持前端的简洁性,我执行了以下操作:

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到控制台。


11

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

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

11

您可以使用此方法中止任何连续的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>

10

没有可靠的方法可以执行此操作,一旦请求继续执行,我什至不会尝试。做出合理反应的唯一方法是忽略响应。

在大多数情况下,它可能会在以下情况下发生:用户单击按钮的次数过多,触发了许多连续的XHR,在这里您有很多选择,要么阻塞按钮直到XHR返回,要么在另一个正在运行的提示时不触发新的XHR用户向后倾斜-或放弃任何未决的XHR响应,但最近的响应。


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


 })
<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!" >

5
请说明如何解决该问题。这将有助于OP和其他未来的搜索者。
SnareChops

5

我遇到了轮询问题,一旦页面关闭,轮询就会继续进行,因此,由于我关闭了页面关闭后的下一个50秒,因为设置了mysql值,所以用户会错过更新,即使我杀死了ajax请求,我想通了,使用$ _SESSION设置变量将不会在民意测验中对其自身进行更新,直到其结束并且有一个新变量开始,所以我所做的是在数据库中将值设置为0 = offpage,而我轮询我查询该行并返回false;当它为0时,轮询中的查询显然会为您提供当前值...

希望这对您有所帮助


5

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

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

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

4

我共享了一个演示,演示了如何取消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);   
});

1
$.ajax提供了一个timeout选项,因此您无需自己编写。只需使用..., data: {...}, timeout: waitTime,...
Bram Vanroy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.