The Codesee
The Codesee

Reputation: 3783

Abort all remaining AJAX requests

I am running an AJAX request when the user types in an input field and then displaying the result on the page. When the user presses the backspace to delete all of what they've inputted, I use .empty to remove the result from the page.

However, if you press the backspaces really quickly, the result is removed from the page, but then because the last AJAX query hasn't last executed, the result from that query appears!!!

I have looked at Abort Ajax requests using jQuery but that didn't help, and have tried adding return: false; after $("#results").empty(); to no avail.

If there are any remaining AJAX calls when if(this.value.length < 1) { is true, I would like to abort them all inside that function.

$("input#enter").keyup(function() {
    if(this.value.length < 1) {
        $("#display").empty();
    }else{ 
        $.ajax({
            type: "POST",
            url: "getdata.php",
            data: "title=" + this.value,
            success: function(data) {
                $("#display").empty(); 
                $("#display").html(data);
            }
        });
    } 
});

Upvotes: 2

Views: 772

Answers (2)

David Knipe
David Knipe

Reputation: 3454

You talk about aborting ajax requests. It would be sufficient to wait until the request returns and then simply do nothing. Yes, if you were doing a lot of large requests it might improve performance if you cancelled them. But that means using jqXhr objects, and personally I prefer to stick to jQuery where possible.

You could have a variable telling you how up-to-date the #display is. It would store the time of sending of the last ajax request that was used to update it. If you get a response from an earlier request, ignore it.

var lastUpdateTime = 0;

$("input#enter").keyup(function() {
    var now = new Date().getTime();
    if(this.value.length < 1) {
        $("#display").empty();
        lastUpdateTime = now;
    }else{ 
        $.ajax({
            type: "POST",
            url: "getdata.php",
            data: "title=" + this.value,
            success: function(data) {
                if (now < lastUpdateTime) {
                    return;
                }
                $("#display").empty(); 
                $("#display").html(data);
                lastUpdateTime = now;
            }
        });
    } 
});

Upvotes: 0

guest271314
guest271314

Reputation: 1

You can use $.active to check if $.ajax() call is active before calling next $.ajax()

$("input#enter").keyup(function() {
    if(this.value.length < 1) {
        $("#display").empty();
    }else{ 
      if (!$.active) {
        $.ajax({
            type: "POST",
            url: "getdata.php",
            data: "title=" + this.value,
            success: function(data) {
                $("#display").empty(); 
                $("#display").html(data);
            }
        });
      }
    } 
});

You can also include attaching .ajaxComplete() to document to call next $.ajax() call when current call completes

function request(value) {
  return  $.ajax({
            type: "POST",
            url: "getdata.php",
            data: "title=" + value,
            success: function(data) {
                $("#display").empty(); 
                $("#display").html(data);
            }
        });
}

$("input#enter").keyup(function() {
    if(this.value.length < 1) {
        $("#display").empty();
    }else{ 
      if (!$.active) {
        request(this.value)
      } else {
        $(document).one("ajaxComplete", function() {
          request(this.value)
        })
      }
    } 
});

One approach to abort requests is to use XMLHttpRequest(), push requests to an array, then call .abort() on each element of the array

function request(data) {
  let fd = new FormData();
  fd.append("html", data);
  fd.append("delay", Math.floor(Math.random() * 10));
  let xhr = new XMLHttpRequest();
  xhr.open("POST", "/echo/html/", true);
  xhr.onload = function() {
    console.log(xhr.responseText);
  }
  xhr.onabort = function() {
    console.log("request " + requests.indexOf(xhr) + " aborted")
  }
  xhr.send(fd);
  return xhr
}

function abortAllRequests() {
  requests.forEach(function(xhr, index) {
    xhr.abort()
  })
}

var requests = [];

requests.push(request(123), request(456));

abortAllRequests();

jsfiddle https://jsfiddle.net/onguym5y/

Upvotes: 1

Related Questions