Search code examples
javascriptargumentsclosuresdebouncing

How to pass in arguments in debounce


const debounce = (func) => {
    return (arg) => {
        let timeoutId;
        if (timeoutId){
            clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
            func(arg);
        }, 1000);
    }
}

function hello(name){
    console.log("hello " + name);
}

input.addEventListener("input", debounce(hello));

In this example how am I suppose to debounce and call the hello function with a debounce and the name "Brian".

On code line 2 return (arg) => { what is the code to pass an argument in the variable?

I get that debounce(hello); calls the debounce function but how am I suppose to pass in a variable so it gets stored in (arg)?


Solution

  • When you return a function from a function, you have two sets of arguments: those to the outer function and those to the inner function, so the pattern is essentially

    debounce(someFunction)("argument 1 to someFunction", "argument 2 to someFunction");
    

    You can spread this over a few lines. The pattern is known as currying.

    Note that your debouncer function isn't correct. It's delaying, but not batching updates because the timeoutId is local to the returned function, defeating the purpose of the closure.

    Also, using ...args instead of args and making the timeout a parameter rather than hardcoding it in the function makes the debounce a bit more resuable.

    Here's a minimal example of all of this:

    const debounce = (func, timeout=1000) => {
      let timeoutId;
      return (...args) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
          func(...args);
        }, timeout);
      };
    };
    
    const hello = name => console.log("hello " + name);
    const debouncedHello = debounce(hello);
    document.querySelector("input")
      .addEventListener("input", e => debouncedHello(e.target.value));
    <input value="test">