Debounce function that limits the rate a callback is triggered. Which implementation is better, and why? The Debounce technique allow us to “group” multiple sequential calls in a single one - The debounce() function forces a function to wait a certain amount of time before running again.
I wrote both debounce_1 &amp; debounce_2 functions while solving a programming challenge, they produce the same result but I want to know which implementation is better and why, as I'm currently studying JavaScript to improve the quality of my code.


/* Write a function called 'debounce' that accepts a function and returns a 
   new function that only allows invocation of the given function after 
   'interval' milliseconds have passed since the last time the returned 
   function ran.

   Additional calls to the returned function within the 'interval' time 
   should not be invoked or queued, but the timer should still get reset. */

function debounce_1(callback, interval) {
  let lastTime = -Infinity;
  
  return function(){
    let now = Date.now(), res;
    
    if (now - lastTime &gt; interval) {
      res = callback();
    }
    
    lastTime = now;
    return res;
  }
}

function debounce_2(callback, interval) {
  let timeout = null;
  
  return function(){
    let res;
    
    if (!timeout) { res = callback(); }
    
    clearInterval(timeout);
    timeout = setTimeout(() =&gt; timeout = null, interval);
    
    return res;
  }
}

/* TESTING */
function hello() { return 'hello'; }

// UNCOMMENT BELOW TO TRY EITHER ONE:
const sayHello = debounce_1(hello, 3000);
// const sayHello = debounce_2(hello, 3000);

console.log( sayHello() );                                 // -&gt; 'hello'
setTimeout(function() { console.log(sayHello()); }, 2000); // -&gt; undefined
setTimeout(function() { console.log(sayHello()); }, 4000); // -&gt; undefined
setTimeout(function() { console.log(sayHello()); }, 8000); // -&gt; 'hello'
I think the solution with the timeout variable is far more clear, and avoids arithmetic operations. However, your implementation has some odd behaviours. That is, using debounce with a high frequency will postpone the callback indefinitely.
const debounce = (func, interval) =&gt; {
    let timeout = null;
    return ()=&gt;{
        if (timeout) return undefined;
        timeout = setTimeout( ()=&gt;timeout=null, interval)
        return func();
    }
}

As an alternative, I propose this. Using this code, the timeout is only set when an actual function call occurs.