【问题标题】:Abort new AJAX request before completing the previous one在完成前一个之前中止新的 AJAX 请求
【发布时间】:2013-10-15 04:15:47
【问题描述】:

我有一个函数可以在输入更改时运行 AJAX 调用。

但是,在上一个 ajax 调用完成之前,该函数有可能再次被触发。

我的问题是,如何在开始新的 AJAX 调用之前中止以前的 AJAX 调用? 不使用全局变量。 (查看类似问题的答案here

JSFiddle 我当前的代码:

Javascript:

var filterCandidates = function(form){
    //Previous request needs to be aborted.
    var request = $.ajax({
        type: 'POST',
        url: '/echo/json/',
        data: {
            json: JSON.stringify({
                count: 1
            })
        },
        success: function(data){
            if(typeof data !== 'undefined'){
                jQuery('.count').text(data.count)
                console.log(data.count);
            }
        }
    });
};

if(jQuery('#search').length > 0){
    var form = jQuery('#search');
    jQuery(form).find(':input').change(function() {
        filterCandidates(form);
    });
    filterCandidates(form);
}

HTML:

<form id="search" name="search">
    <input name="test" type="text" />
    <input name="testtwo" type="text" />
</form>
<span class="count"></span>

【问题讨论】:

  • 你的问题标题有误,应该是Abort new AJAX request before completion of the previous

标签: javascript ajax jquery


【解决方案1】:
 var currentRequest = null;    

currentRequest = jQuery.ajax({
    type: 'POST',
    data: 'value=' + text,
    url: 'AJAX_URL',
    beforeSend : function()    {           
        if(currentRequest != null) {
            currentRequest.abort();
        }
    },
    success: function(data) {
        // Success
    },
    error:function(e){
      // Error
    }
});

【讨论】:

  • 不应该两个响应处理程序(successerror)都将currentRequest 设置回null
  • 啊,不。 beforeSend 正在执行之前 jqXHR 对象被分配给currentRequest。因此,先前的呼叫在此中止。 -- 总是感谢评论良好的答案
  • 此解决方案不适用于 GET 类型的我。没有用 POST 检查。
  • 虽然此代码可以回答问题,但提供有关 如何为什么 解决问题的附加上下文将提高​​答案的长期价值。
  • 像魅力一样工作。对于它不起作用的人,也许您在进行 ajax 调用的函数内部初始化 currentRequest=null 时犯了一个错误,请尝试在函数外部对其进行初始化。我犯了那个错误;)
【解决方案2】:
var filterCandidates = function(form){
    //Previous request needs to be aborted.
    var request = $.ajax({
        type: 'POST',
        url: '/echo/json/',
        data: {
            json: JSON.stringify({
                count: 1
            })
        },
        success: function(data){
            if(typeof data !== 'undefined'){
                jQuery('.count').text(data.count)
                console.log(data.count);
            }
        }
    });
    return request;
};

var ajax = filterCandidates(form);

保存在一个变量中,然后,在第二次发送之前,检查它的readyState 并在需要时调用abort()

【讨论】:

  • 这比我想象的要容易。我已经为任何感兴趣的人创建了这个工作的小提琴:jsfiddle.net/YzDBg/4。谢谢。
  • 你能详细解释一下吗?
【解决方案3】:

已接受答案的变体并从对该问题的评论中采用 - 这对我的应用程序非常有用....

使用 jQuery 的 $.post()....

var request = null;

function myAjaxFunction(){
     $.ajaxSetup({cache: false}); // assures the cache is empty
     if (request != null) {
        request.abort();
        request = null;
     }
     request = $.post('myAjaxURL', myForm.serialize(), function (data) {
         // do stuff here with the returned data....
         console.log("returned data is ", data);
     });
}

根据需要多次调用 myAjaxFunction(),它会杀死除最后一个之外的所有内容(我的应用程序上有一个“日期选择器”,并根据所选日期更改价格 - 当有人在没有上述代码的情况下快速点击它们时,他们是否会得到合适的价格是一个抛硬币的问题。有了它,100% 正确!)

【讨论】:

    【解决方案4】:
    if(typeof window.ajaxRequestSingle !== 'undefined'){
      window.ajaxRequestSingle.abort();
    }
    
    window.ajaxRequestSingle = $.ajax({
      url: url,
      method: 'get',
      dataType: 'json',
      data: { json: 1 },
      success: function (data) {
        //...
      },
      complete: function () {
        delete window.ajaxRequestSingle;
      }
    });
    

    【讨论】:

      【解决方案5】:

      试试这个代码

      var lastCallFired=false;
      
      var filterCandidates = function(form){
      
          if(!lastCallFired){
          var request = $.ajax({
              type: 'POST',
              url: '/echo/json/',
              data: {
                  json: JSON.stringify({
                      count: 1
                  })
              },
              success: function(data){
                  if(typeof data !== 'undefined'){
                      jQuery('.count').text(data.count)
                      console.log(data.count);
                  }
              }
          });
              setInterval(checkStatus, 20);
      
          }
      
      };
      
      if(jQuery('#search').length > 0){
          var form = jQuery('#search');
          jQuery(form).find(':input').change(function() {
              filterCandidates(form);
          });
          filterCandidates(form);
      }
      
      var checkStatus = function(){
              if(request && request.readyState != 4){
                  request.abort();
              }
          else{
              lastCallFired=true;
          }
      };
      

      【讨论】:

        最近更新 更多