1

I have a jQuery datatable that immediately loads ON READY. After that, the datatable is reloaded every 30 seconds. This feature is functioning properly.

I have added a search feature that automatically reloads the datatable with new search results. This part is also functioning properly.

The problem I am experiencing is when I am using the search feature, and the new search results are returned. After 30 seconds, the new results are cleared and the datatable reloads with all of the original records.

Here is what I am currently attempting:

$(document).ready(function()
{
  var searchCriteria = "";
  displayBookings(searchCriteria);

  var idle = 0;
  var idleInterval = setInterval(timer, 30000);
  $(this).mousemove(function(e){idle = 0;});
  $(this).keypress(function(e){idle = 0;});
  function timer()
  {
    idle = idle + 1;
    if(idle > 2)
    {
      displayBookings(searchCriteria);
      console.log('table reloaded');  
    }
  }

  $('#searchPending').on('click', function()
  {
    var isPending = 'Y';
    var searchCriteria = {
      isPending: isPending
    };
    displayBookings(searchCriteria);
  });
});

The function displayBookings() takes searchCriteria. If searchCriteria is blank, then a basic query is fired. Obviously is searchCriteria contains parameters, then the same query is fired with a WHERE clause attached. I did not disclose the code for displayBookings().

All I need to do is stop the 30 second interval if the #searchPending button is clicked.

halfer
  • 19,824
  • 17
  • 99
  • 186
John Beasley
  • 2,577
  • 9
  • 43
  • 89
  • 1
    In addition to CodeAt30's answer, why not simply modify `searchCriteria` in the click handler rather than declare a new variable? Make some "global" state object to hold the search criteria. Btw: what you're doing with your timer is called `debouncing`. [If using lodash, they have a function](https://lodash.com/docs/4.17.4#debounce). – noahnu Feb 01 '18 at 19:06
  • Would you be so kind as to provide an example of what you are referring to? I did mark already mark this question as answered, however I would be interested to see what you are talking about. Also, is debouncing a good thing or bad? – John Beasley Feb 01 '18 at 19:27
  • I posted an answer using the single "state". I misread your code originally. You're not debouncing, although I provided a note about that in my answer if you're curious. – noahnu Feb 01 '18 at 21:56

2 Answers2

1

Clear the interval so it will stop loading.

clearInterval(idleInterval)

specifically in your code:

$('#searchPending').on('click', function()
  {
    clearInterval(idleInterval)
    var isPending = 'Y';
    var searchCriteria = {
      isPending: isPending
    };
    displayBookings(searchCriteria);
  });
CodeAt30
  • 874
  • 6
  • 17
  • Where would I put that? Inside the button click? – John Beasley Feb 01 '18 at 19:04
  • 1
    @JohnBeasley Yup, i just edited to show that. just call that when the button is clicked, it will clear out the interval and will stop the refresh-load from going on any longer. – CodeAt30 Feb 01 '18 at 19:06
  • 1
    This seems to be what I was looking for. I did not even know about the clearInterval feature. Thank you, sir. – John Beasley Feb 01 '18 at 19:25
1

Rather than start and stop the timer interval, since you'll run into a bit of a race condition, you can just have the "refresh" (your "timer" function) refresh using the latest search criteria. To do this, just pass the same object into your displayBookings function. E.g.

const search = { criteria: "" };
$(...).click(() => {
    search.criteria = 'change it...';
    displayBookings(search.criteria);
});

setInterval(() => displayBookings(search.criteria), 30000);

This way, if a refresh happens, it will use the latest search.criteria. You can achieve the same result with minimal change in your code by simply removing the var from the second searchCriteria. Currently, without removing the var, your outer criteria is being "shadowed" by your inner.

I alluded to debouncing1 in one of my comments. I misread the code and debouncing is not what you want. Instead, you want to only "refresh" if there hasn't been any user activity within some threshold. Here's an alternative from the approach you used:

let lastInteraction = 0;

function interact() {
    lastInteraction = Date.now();
}

$(this).mousemove(interact);
$(this).keypress(interact);

Then in your refresh function:

if (Date.now() - lastInteraction > threshold) { ...

Implementing both the central criteria and revised idle check:

$(document).ready(function() {

  const idle = {
    threshold: 1000,
    lastInteraction: 0,
    interact() {
      idle.lastInteraction = Date.now();
    },
    isIdle() {
      return Date.now() - idle.lastInteraction > idle.threshold;
    }
  };

  const search = { criteria: "" };

  $(this).mousemove(idle.interact);
  $(this).keypress(idle.interact);

  setInterval(() => {
    if (idle.isIdle()) {
      displayBookings(search.criteria);
    }
  }, 30000);

  $('#searchPending').on('click', () => {
    search.criteria = { isPending: 'Y' };
    displayBookings(search.criteria);
  });

  displayBookings(search.criteria);
});

1 The Wikipedia article linked to discusses debouncing with a keyboard. It's the same concept. You'd use debouncing on your displayBookings function if you plan on having it execute live as the user is typing. This would prevent too many HTTP requests from happening in a short duration of time.

noahnu
  • 3,479
  • 2
  • 18
  • 40