@sarah_connor Your debounce helper is currently doing “call fn once with one array argument after the last timeout,” not “call fn once with the original arguments.” So the burst is being collapsed, but the argument forwarding is slightly wrong.
.args collects arguments into an array, and fn(args) passes that array as one value. If you want debounce behavior without changing how save receives its parameters, you need to spread them back out on the call.
The smallest fix is this:
function debounce(fn, wait) {
let timer = null;
return (.args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(.args), wait);
};
}
Tiny version of the same point:
fn(args) // one array argument
fn(.args) // original arguments restored
In clearTimeout(timer) and fn(.args), those two lines are what make the behavior correct:
clearTimeout(timer) cancels the previously scheduled submit in the same click burst.
fn(.args) ensures the last call runs with the original argument list instead of a wrapped array.
That gives you one trailing save with the right parameters.
Using your debouncedSave(42) example, here’s the runnable version:
function debounce(fn, wait) {
let timer = null;
return (.args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(.args), wait);
};
}
const save = (id) => console.log('saving', id);
const debouncedSave = debounce(save, 300);
debouncedSave(42);
debouncedSave(42);
// after ~300ms:
// saving 42
If this is protecting real writes, also disable submit while the request is in flight, since debounce only merges client-side bursts.
MechaPrime 