Search code examples
javascripttimerevent-looptask-queuedebouncing

clearTimeout doesn't clear timer, it seems too late to clear it


I'm trying to console.log the input value when the keyup event get fired, but similar to debounce implementation, from all posible events happened within a range of 1000 miliseconds I want the last one to be fired.

With clearTimeout(timer) any previous timer get cleared then a fresh timer is set. So from my view, on entering a string the logs would be like:

g
ggg
gggggg
ggggggg

Never be repeted.

      let timer = null;
      
      function withdelay() {
        clearTimeout(timer);
        timer = setTimeout(() => {
          handleChange();
        }, 1000);
      }

      function handleChange() {
        console.log(document.getElementById("texto").value);
      }
 <input type="text" id="texto" onkeyup="withdelay()" />

The problem comes when the time between keyup events is close to the delay (1000 miliseconds), the logs are the same.
enter image description here

Why does that happen?, is there any solution based on this lines?

Here is what I think; once the callback of the timer is load from the task queue to the call stack to be executed the clearTimeout(timer) cannot take effect so the callback continue its execution.


Solution

  • The problem here is how keypress vs keyup fires.

    • keypress fires when the character is added.
    • keyup is fired when the key is done being pressed.

    So when you release the key the value has already been written. It is not written when you release the key. So the timer picks up the change slightly before you release.

    Depending on what you are actually trying to do you may want to use oninput or onkeydown