Skip to content
Jobless Busters
Runs testsIntermediate

Write debounce

Debounce delays running a function until no further call arrives for a given time. Write debounce(fn, wait) in the trailing version, with no call at the start of a burst.

The returned function must keep the caller's this and the latest arguments, and a cancel() method must cancel the scheduled call (useful for cleanup).

This is the basic interview version, without leading, maxWait or returning a Promise.

  • Manage a timer in a closure
  • Keep this and the arguments
  • Expose cancel
  • d(1); d(2); d(3) // at intervals shorter than wait→ fn called once, with argument 3, after wait ms of quiet
The 5 tests

Tests written from the card's description (trailing variant, this, latest arguments, cancel). They use real timers, so they take a fraction of a second.

calls fn once, after the quiet period, with the latest arguments

JavaScript
const calls = [];
const d = debounce((...args) => calls.push(args), 30);
d(1); d(2); d(3);
assert.deepEqual(calls, [], 'fn should not be called straight away');
await sleep(80);
assert.deepEqual(calls, [[3]]);

another call pushes the deadline back

JavaScript
const calls = [];
const d = debounce(x => calls.push(x), 60);
d('a');
await sleep(40);
d('b');
await sleep(40);
assert.deepEqual(calls, [], '40 ms after the second call, wait has not elapsed yet');
await sleep(70);
assert.deepEqual(calls, ['b']);

keeps the caller's this

JavaScript
let seen;
const counter = { name: 'counter', run: debounce(function () { seen = this && this.name; }, 10) };
counter.run();
await sleep(50);
assert.equal(seen, 'counter');

cancel cancels the scheduled call

JavaScript
let calls = 0;
const d = debounce(() => calls++, 20);
d();
assert.equal(typeof d.cancel, 'function', 'the returned function should have a cancel method');
d.cancel();
await sleep(60);
assert.equal(calls, 0);

separate bursts call fn separately

JavaScript
const calls = [];
const d = debounce(x => calls.push(x), 20);
d(1);
await sleep(60);
d(2);
await sleep(60);
assert.deepEqual(calls, [1, 2]);

Source: Full Stack / JS — task card — The task and reference solution come from the card; the tests were written from its description.

JavaScript · runs in a Web Worker in your browser

Tab indents · Esc, then Tab, leaves the editor · ⌘/Ctrl + Enter runs the tests · Your code is saved in this browser.

Run the tests to check your solution. 5 predefined tests.

Stuck? Hints go from gentle to specific.

Give it a real try first — the solution is most useful after you've struggled a bit.