在返回之前取消jQuery AJAX调用?

时间:2009-09-16 17:50:53

标签: jquery ajax

我打开了一个jQuery对话框,然后进行了AJAX调用。我想这样做,如果关闭对话框或按下取消按钮,AJAX调用将被取消,并且不会调用其回调函数。我可以想办法用这样的变量来做到这一点:

  function doStuff(){
    var doCallback = true;
    $('#dialog').dialog({
      title: 'Dialog Title',
      modal: true,
      buttons: {
        Cancel: function() {
          doCallback = false;
          doSomethingElse();
        }
      }
    });
    $.get('url/url/url', function(data){
      if(doCallback){
        doTheSuccessThing(data);
      }
    });
  }

但是,不知怎的,这对我来说感觉很脏,并且实际上并没有阻止AJAX调用完成。是否有内置方法取消正在进行的AJAX调用?

5 个答案:

答案 0 :(得分:17)

当我有一个可能被多次触发的回调,但我想只使用最后一个,我使用这种模式:

var resultsXHR, resultsTimer, resultsId=0;
$('input').keyup(function(){
  clearTimeout(resultsTimer);                     // Remove any queued request
  if (resultsXHR) resultsXHR.abort();             // Cancel request in progress
  resultsTimer = setTimeout(function(){           // Record the queued request
    var id = ++resultsId;                         // Record the calling order
    resultsXHR = $.get('/results',function(data){ // Capture request in progress
      resultsXHR = null;                          // This request is done
      if (id!=resultsId) return;                  // A later request is pending
      // ... actually do stuff here ...
    });  
  },500);                                         // Wait 500ms after keyup
});

abort()不足以阻止调用成功回调;即使您尝试取消请求,您仍可能会发现回调运行。这就是为什么必须使用resultsId跟踪器并让你的回调停止处理,如果另一个,稍后重叠的回调准备就绪。

鉴于这是多么常见和繁琐,我认为以一种可重复使用的方式将其包装起来是一个好主意,这种方式不需要为每个想要处理的每个变量名称提供一个独特的三元组本地变量名称:

(function($){
  $.fn.bindDelayedGet = function(event,delay,url,dataCallback,dataType,callback){
    var xhr, timer, ct=0;
    return this.bind(event,function(){
      clearTimeout(timer);
      if (xhr) xhr.abort();
      timer = setTimeout(function(){
        var id = ++ct;
        xhr = $.get(url,dataCallback && dataCallback(),function(data){
          xhr = null;
          if (id==ct) callback(data);
        },dataType);
      },delay);
    });
  };
})(jQuery);

// In action
var inp = $('#myinput').bindDelayedGet('keyup',400,'/search',
  function(){ return {term:inp.val()}; },
  'html',
  function(html){ $('#searchResults').clear().append(html); }
);

您可以更详细地找到上面讨论的代码on my website

答案 1 :(得分:14)

好的,基于使用$ .get函数返回的XmlHttpRequest对象的建议,我提出了这个:

function doStuff(){
    var ajaxRequest = $.ajax({
                        url : 'url/url/url',
                        type : "GET",
                        success : function(data){
                          ajaxRequest = null;
                          doSuccessStuff(data);
                        }
                      });

    $('#dialog').dialog({
      title: 'Stuff Dialog',
      bgiframe: true,
      modal: true,
      buttons: {
        Cancel: function() {
          if (ajaxRequest)
            ajaxRequest.abort();
          doCancelStuff();
        }
      }
    });
  }

对我来说似乎工作和感觉更清洁。

答案 2 :(得分:5)

jQuery中没有方法,但你可以使用从jQuery get / post / ajax函数返回的XmlHttpRequest对象。

来自jQuery blog

// Perform a simple Ajax request
var req = $.ajax({
  type: "GET",
  url: "/user/list/",
  success: function(data) {
    // Do something with the data...
    // Then remove the request.
    req = null;
  }
});

// Wait for 5 seconds
setTimeout(function(){
  // If the request is still running, abort it.
  if ( req ) req.abort();
}, 5000);

答案 3 :(得分:4)

看来是这样,虽然我从来没有这样做过。

$.get会返回XmlHttpRequest个对象,该对象可以调用abort()方法。也许试试吧?

答案 4 :(得分:0)

如果你在脚本中添加一个条件你ajax到条件为真的你输出你的html,否则,你不输出任何东西,然后你可以做简单的if(html)检查成功函数这样:

$.ajax({
      type: "GET",
      url: "url.php",
      data: "data="+data,
      success: function(html)
          { 
              if(html){
              $("#container").empty().html(html);
              }
      }
});

在这个例子中,url.php看起来像这样:

$data = $_GET['data'];

if($data=="whatever"){
     echo "<div>Hello</div>";
}else{}

这对我有用。我知道这篇文章很老,但希望它可以帮助别人。