1

From this How to delay the .keyup() handler until the user stops typing? question we've learned how to create delays. But any ideas on how do I cancel delayed event?

Check this out

In this example I don't want anything to be printed out after clicking the cancel button.

But I need more extensible solution. The solution might be to modify the delay() function somehow like this

delay(fn, ms, cancelCallback)

In here the cancelCallback would be a function that cancels the delay. By cancels the delay I mean to not call the fn() and just do nothing.

const inputElement = document.getElementById('input');
const buttonElement = document.getElementById('button');
const pElement = document.getElementById('p');

const delayInMs = 2000; // 2s delay

const delay = function (fn, ms) {
  let timer = 0;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(fn.bind(this, ...args), ms || 0);
  };
};

const print = text => pElement.innerHTML = text;

const handleKeyUp = e => print(e.target.value);

inputElement.addEventListener('keyup', delay(handleKeyUp, delayInMs));


// Some new logic
const cancelDelay = () => {};

inputElement.addEventListener('click', cancelDelay);
<input id="input" />
<button id="button">Cancel</button>

<br />

<h6>You typed:</h6>
<p id="p"></p>

2 Answers2

2

I figured this one out on my own. I think the solution is pretty clear.

const inputElement = document.getElementById('input');
const buttonElement = document.getElementById('button');
const pElement = document.getElementById('p');

const delayInMs = 2000; // 2s delay

// Modified
function delay(fn, ms) {
  let timer = 0;
    return {
      call(...args) {
        clearTimeout(timer);
        timer = setTimeout(fn.bind(this, ...args), ms || 0);
      },

      cancel() {
        clearTimeout(timer);
      },
    };
}

// Just show text
const print = text => pElement.innerHTML = text;

const myFunc = text => print(text);

const myFuncDelayed = delay(myFunc, delayInMs);

// Calling
const handleInputKeyUp = e => myFuncDelayed.call(e.target.value);
inputElement.addEventListener('keyup', handleInputKeyUp);


// Canceling 
const handleBtnClick = () => { myFuncDelayed.cancel() };
buttonElement.addEventListener('click', handleBtnClick);
<input id="input" />
<button id="button">Cancel</button>

<br />

<h6>You typed:</h6>
<p id="p"></p>
0

First you need to add cancel handler for the buttonElement not for inputElement. In order to check if the cancel button has been clicked you can have one global variable flag and check if that is true which can be set to true when cancel button is clicked. Also, make sure to reset it to default on your input keyup handler.

const inputElement = document.getElementById('input');
const buttonElement = document.getElementById('button');
const pElement = document.getElementById('p');

const delayInMs = 2000; // 2s delay

let isCancelled = false;

const delay = function (fn, ms) {
  let timer = 0;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(fn.bind(this, ...args), ms || 0);
  };
};

const print = text => pElement.innerHTML = text;

const handleKeyUp = e => {
 if (!isCancelled) {
    print(e.target.value)
  }
  
  isCancelled = false;
};

inputElement.addEventListener('keyup', delay(handleKeyUp, delayInMs));


// Some new logic
const cancelDelay = () => { isCancelled = true };

buttonElement.addEventListener('click', () => cancelDelay());
<input id="input" />
<button id="button">Cancel</button>

<br />

<h6>You typed:</h6>
<p id="p"></p>
Yadab
  • 1,767
  • 1
  • 10
  • 16
  • Pretty good solution, but if you have 1000 delays it gets messy. Check out mine, I figured this one out –  Apr 20 '21 at 00:59