Deepak
Deepak

Reputation: 1068

input onKeyUp Event with timeout

I am trying to create a simple debounce for text input. Following is the code:

<body>
    <input id="myInput" type="text" />
</body>
<script>
    function save(data) {
        console.log('saved!!', myInput.value);
    }

    //function process(e, callback, delay) { signature is changed like this, when we call onKeyUp
    function process(callback, delay) { //signature is changed to this, when we call 'process' directly
        //console.log('e', e, 'callback', callback, 'delay', delay);
        let timer;
        return function () {
            clearTimeout(timer);
            timer = setTimeout(callback, delay);
        }
    }

    function onKeyUp(e) {
        //console.log('onKeyUp')
        process(e, save, 1000)
    }

    //const inp = document.querySelector("#txtInput");
    const inp = document.getElementById("myInput");
    inp.addEventListener(
        'keyup',
        //process(save, 1000) //works
        onKeyUp //-- > does not work
    );
</script>

If I simply call process function on keyup event, it works as expected.

However, I also want to pass e.target.value, and hence I want to event object as well. Hence, to achieve that when I tried calling another function called onKeyUp , which captures event object and when I pass it to process(e, save, 1000) the setTimeout isn't getting called and hence save function isn't getting triggered.

My question is what is the difference when we call process funtion directly on event listener and when we call another function and pass event object to it.

Upvotes: 0

Views: 496

Answers (1)

Taurz
Taurz

Reputation: 390

The process(save, 1000) works because it return a function (the anonymous function returned in process()) which passes to inp.addEventListener as the second parameter

inp.addEventListener(
    'keyup',
    process(save, 1000)
);
// equals to 
const callback = process(save, 1000); //get the anonymous function returned in `process()`
inp.addEventListener(
    'keyup',
    callback
); //callback will be called like callback() when keyup

but when change it to onKeyup, the anonymous function will not be called, so the setTimeout won't work, so does the save function

inp.addEventListener(
    'keyup',
    onKeyup
); // onKeyup will be called like onKeyup() 
function onKeyUp(e) {
    process(e, save, 1000) // process called
}
function process(e, callback, delay) { 
    let timer;
    return function () { // not called, it returns as a function only
        clearTimeout(timer);
        timer = setTimeout(callback, delay);
    }
}

To fix it. you can do

function onKeyUp(e) {
    process(e, save, 1000)(); 
}
let timer; //assign the `timer` as a global variable
function process(e, callback, delay) { 
    return function () {
        clearTimeout(timer);
        timer = setTimeout(callback, delay);
    }
}

More further, you don't need onKeyup if you just want to get the event parameter.In the first code, the anonymous function was called when keyup, it accepted the event parameter already.

function process(callback, delay) { 
    let timer;
    return function (e) { // you can get `e` here
        clearTimeout(timer);
        timer = setTimeout(callback, delay);
    }
}

Upvotes: 1

Related Questions