Why does this debounce helper lose the latest arguments when calls happen rapidly?

I wrote a small debounce utility for an input handler, but when I trigger it several times quickly, it sometimes logs an older value instead of the most recent one. What is wrong with this implementation?

function debounce(fn, wait) {
  let timer, lastArgs;
  return function (...args) {
    lastArgs = args;
    if (timer) clearTimeout(timer);
    timer = setTimeout(fn(lastArgs), wait);
  };
}

const log = debounce((v) => console.log(v), 200);

BayMax

setTimeout(fn(lastArgs), wait) calls fn immediately and stores its return value as the timer callback, so rapid calls race against already-executed work.

MechaPrime :slightly_smiling_face:

Your fn(lastArgs) line is the culprit MechaPrime pointed at, and there’s a second snag because it passes the whole args array as one value, so defer a wrapper like setTimeout(() => fn(.lastArgs), wait) if you want the newest call to survive the stampede.

Arthur