0

I have a function which calls to the backend to retrieve information and then displays it. My problem is if the user goes back and forth over many cells, it seems to not catch up in time and display everything the user went over instead of what the current cell is, like its lagging bad displaying multiple elements instead of the intended one. Is there a way to make sure that it only happens to the current cell instead of it lagging bad and catching up?

$('body').on('mouseenter', '.cell', function (e) {
    var cellNumber = $(this).attr("cellNumber");
    // load the data via ajax
    $.get('/Main/Sub', { cellNumber: cellNumber },
        function(responseText){
          // code
     }).on('mouseout', function(){
        $(this).remove();
     });
});
Keith
  • 4,059
  • 2
  • 32
  • 56
  • Possible duplicate of [Abort Ajax requests using jQuery](https://stackoverflow.com/questions/446594/abort-ajax-requests-using-jquery) – Andrew Dec 18 '17 at 20:14
  • You could use a timeout, abort stuff, etc, but the better solution would be to simply throttle or debounce it, or to eliminate the need to perform this ajax request. The latter option would likely be far more user friendly. – Kevin B Dec 18 '17 at 20:21

4 Answers4

0

So AFAIK you can't cancel an AJAX request once it's made. What you might want to do is check to see if the element has been removed in the AJAX callback.

$('body').on('mouseenter', '.cell', function(e) {
  var cellNumber = $(this).attr("cellNumber");

  // load the data via ajax
  $.get('/Main/Sub', {
    cellNumber: cellNumber
  }, function(responseText) {

    // AJAX has finished double check that this element has not been removed
    if (this.parentNode) {
      // node has not been removed, do some cool stuff
    }

  }.bind(this))

  $(this).on('mouseout', function() {
    $(this).remove();
  });
});

Check this out though

I hate when people give best practice advice and refuse to answer the question so now that I've answered the question I'll give you some advice haha.

I would suggest not sending AJAX request on mouse over. A user can accidentally trigger hundreds of AJAX requests simply by moving their mouse around. You waste bandwidth, CPU, and you may potentially jam up your server because a couple of users moving their cursor around could DoS your server.

Maybe consider changing your UI/UX to a click event or maybe delay sending the ajax until the cursor has hovered over an element for a while.

Shawn Whinnery
  • 3,519
  • 3
  • 16
  • 16
0

I would consider a debounce here.

// one debounce function, there are several that are similar in form just do a search...
function debounce(fn, delay) {
  var timer = null;
  return function () {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
}

$('body').on('mouseenter', '.cell', debounce(function (event) {
  // do the Ajax request
}, 250));

Note you could also as part of your "ajax" check to see if a given "cell" has previously been processed, if not stash the results somewhere - like in a data attribute and get from there if it exists (or is outside some time limit) instead of the ajax call. OR wrap that debounce in that "check prior" functionality.

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
0

Previous answers are correct n that you cant cancel an inflight ajax request...however theres nothing from stoping you from ignoring it if it is too late to the party.

At a bare minimum a setTimeout call could be used to prevent this, where the setTimeout only executes whats inside if the response hasnt come back yet.

Pseudo code:

setTimeout(1000, function(){ window.ignoreResponse = true; });
$.get(something) and then:
    if (window.ignoreResponse === false) {
        do x
    }
    else {
        window.ignoreResponse = false; // to reset for the next response
    }
}

If theres multiple of these requests running concurrently you might want to just have the ignoreResponse be a timestamp thats referenced as an object or put the responses in a list and take the last request if theres more than one.

Andrew Bowman
  • 798
  • 9
  • 21
-1

I believe the answer to your question lies in this previously asked question. Set timeout for ajax (jQuery)

Please go through jquery's ajax documentation, however you can get the idea from the code snippet below:

$.ajax({
    url: "test.html",
    timeout: 3000 // sets timeout to 3 seconds
    error: function(){
        // will fire when timeout is reached
    },
    success: function(){
        //do something
    },
});
Mujeeb Qureshi
  • 481
  • 4
  • 7