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?
Just use ajax. //check for existing ajax request if(ajax){ ajax. abort(); } //then you make another ajax request $. ajax( //your code here );
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With