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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1434519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 11:27:01  来源:igfitidea点击:

Cancel a jQuery AJAX call before it returns?

jqueryajax

提问by Hector Scout

I have a jQuery dialog box that opens and then an AJAX call is made. I would like to make it so that if the dialog box is closed or the cancel button is pressed the AJAX call is canceled and its callback function is not called. I can think of some ways to do it with a variable like so:

我打开了一个 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);
      }
    });
  }

But, somehow that feels dirty to me and it doesn't actually stop the AJAX call from completing. Is there a built-in way to cancel an AJAX call in progress?

但是,不知何故,这让我觉得很脏,它实际上并没有阻止 AJAX 调用完成。是否有取消正在进行的 AJAX 调用的内置方法?

采纳答案by Hector Scout

Ok, so based off of the suggestion to use the XmlHttpRequest object returned by the $.get function I came up with this:

好的,根据使用 $.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();
        }
      }
    });
  }

It seems to work and feels cleaner to me.

它似乎有效,对我来说感觉更干净。

回答by Phrogz

When I have a callback that may be fired multiple times, but I want to only use the last one, I use this pattern:

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

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

The abort()alone is not sufficient to prevent the success callback from being invoked; you may still find your callback run even though you tried to cancel the request. This is why it's necessary to use the resultsIdtracker and have your callback stop processing if another, later, overlapping callback is ready to go.

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

Given how common and cumbersome this is, I think it's a good idea to wrap it up in a re-usable fashion that doesn't require you to come up with a unique triplet of local variable names for each you want to handle:

鉴于这是多么常见和繁琐,我认为以可重用的方式包装它是个好主意,不需要您为每个要处理的局部变量名称提供唯一的三元组:

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

You can find the above code discussed in more detail on my website.

您可以在我的网站上找到更详细讨论的上述代码。

回答by Technowise

No method in jQuery, but you can just use XmlHttpRequest object returned from the jQuery get/post/ajax functions.

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

From the jQuery blog:

来自jQuery 博客

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

回答by inkedmn

It appears so, though I've never done it.

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

$.getreturns an XmlHttpRequestobject, which has an abort()method you can call. Maybe try that?

$.get返回一个XmlHttpRequest对象,它有一个abort()你可以调用的方法。也许试试那个?

回答by Dante Cullari

If you put a conditional in the script you ajax to where on the condition being true you output your html, else, you don't output anything, then you can do simple if(html) check in the success function like this:

如果您在 ajax 的脚本中放置一个条件,在条件为真时输出您的 html,否则,您不输出任何内容,那么您可以在成功函数中执行简单的 if(html) 检查,如下所示:

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

in this example, url.php could look something like this:

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

$data = $_GET['data'];

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

This worked for me. I know this post is old, but hope it helps someone.

这对我有用。我知道这篇文章很旧,但希望它对某人有所帮助。