89

I have a function that runs an AJAX call on the change of an input.

But, there is a chance that the function will be fired again before the previous ajax call has completed.

My question is, how would I abort the previous AJAX call before starting a new one? Without using a global variable. (See answer to a similar question here)

JSFiddle of my current code:

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>
goto
  • 7,908
  • 10
  • 48
  • 58
CharliePrynn
  • 3,034
  • 5
  • 40
  • 68

5 Answers5

131
 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
    }
});
Siva.Net
  • 1,398
  • 1
  • 9
  • 3
  • 12
    shouldn't both response handlers (`success` and `error`) set `currentRequest` back to `null`? – CodeManX Jan 28 '15 at 13:26
  • 3
    OP asked `how would I abort the previous ajax call`. But here you're aborting tihe `currentRequest`, which is the newer one. Thus, the previous will execute, the new request will be aborted. Right? – phil294 Apr 08 '16 at 14:21
  • 10
    ah, no. `beforeSend` is being executed *before* the `jqXHR` object is assigned to `currentRequest`. Thus, the previous call is aborted there. -- always appreciate well-commented answers – phil294 Apr 08 '16 at 14:34
  • @CoDEmanX, I think it is not necessary. nothing happens when we abort an already finished request. – Arashsoft Aug 18 '16 at 17:09
  • 5
    This solutions is not working for me in GET type. Didn't check with POST. – Sanyam Jain Oct 06 '16 at 09:38
  • This solution is not working for me. I checked with POST – user9437856 Jun 23 '18 at 05:46
  • 5
    While this code may answer the question, providing additional context regarding *how* and *why* it solves the problem would improve the answer's long-term value. – Alexander Jul 30 '18 at 13:58
  • 5
    Works like a charm. For whom it's not working maybe you are making a mistake of initializing the currentRequest=null inside the function that makes the ajax call, try initializing it outside of the function. I did that mistake ;) – Karan Apr 16 '19 at 06:58
  • Working both with GET and POST. I made the same mistake as @Karan mentioned. Make sure to declare `var currentRequest = null;` high enough in your scope. – Jules Colle Feb 11 '20 at 15:51
  • have the same issue, with AJAX POST, if I get error on ajax requests the previous request are pilling up! which is very bad if you have a quota on api backends. Also I need to mention I was getting this only on click on button event inside another one! (initial button > modal confirmation button). Solution worked for me! – Xao Apr 09 '20 at 21:28
11
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);

save in a variable, and then, before sending second time, check its readyState and call abort() if needed

Romko
  • 1,808
  • 21
  • 27
6

a variation on the accepted answer and adopted from a comment on the question - this worked great for my application....

using jQuery's $.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);
     });
}

Call myAjaxFunction() as many times as you like and it kills all except the last one (my application has a 'date selector' on it and changes price depending on the days selected - when someone clicks them fast without the above code, it is a coin toss as to if they will get the right price or not. With it, 100% correct!)

Apps-n-Add-Ons
  • 2,026
  • 1
  • 17
  • 28
1
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;
  }
});
Arthur Shlain
  • 961
  • 10
  • 23
0

Try this code

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;
    }
};
Murali Murugesan
  • 22,423
  • 17
  • 73
  • 120