Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel a jQuery AJAX call before it returns?

Tags:

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:

  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?

like image 416
Hector Scout Avatar asked Sep 16 '09 17:09

Hector Scout


People also ask

How do I cancel a pending ajax request?

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

Can I cancel ajax request?

Most of the jQuery Ajax methods return an XMLHttpRequest (or the equivalent) object, so you can just use abort() . See the documentation: abort Method (MSDN). Cancels the current HTTP request.

How do I stop XHR request?

The XMLHttpRequest. abort() method aborts the request if it has already been sent. When a request is aborted, its readyState is changed to XMLHttpRequest. UNSENT (0) and the request's status code is set to 0.


1 Answers

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 resultsId tracker and have your callback stop processing if another, later, overlapping callback is ready to go.

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.

like image 53
Phrogz Avatar answered Nov 21 '22 21:11

Phrogz