AniUI Academy

Debounce on the leading edge

mediumFunctions & Closures+250 XPPractice

Ordinary debounce is trailing: it waits for quiet, then acts. That is right for a search box and wrong for a button, where the user needs feedback now and protection from double-clicks after. Leading-edge debounce inverts it: act immediately, then swallow everything until things go quiet.

Implement leadingDebounce(fn, wait). It returns a wrapper. If no cooldown is currently pending, the wrapper invokes fn immediately, synchronously, with the same arguments and the same this, and returns fn's return value. Every call — whether or not it invoked fn — then starts a fresh cooldown of wait milliseconds, restarting any cooldown already running. While a cooldown is pending, calls do not invoke fn and return undefined. Only once a full wait has passed with no calls at all does the next call invoke fn again. There is no trailing call: the calls swallowed during a cooldown are never run later.

Arguments

fnFunction
The function to invoke on the leading edge.
waitnumber
Length of the cooldown, in milliseconds. The cooldown restarts on every call.

Returns

Function — A wrapper that fires on the first call of a burst, then swallows everything until things go quiet.

Examples

const submit = leadingDebounce(() => console.log("submit"), 500);

submit(); // logs "submit" immediately
submit(); // ignored — cooldown active
submit(); // ignored — cooldown restarted

// 500ms of silence later:
submit(); // logs "submit" again

Perfect for a submit button where waiting for the trailing edge feels broken.

const double = leadingDebounce((n) => n * 2, 50);

double(5); // 10 — leading call returns fn's value
double(6); // undefined — suppressed

What it has to do

  • Invoke fn synchronously on the first call and return its result.
  • Suppress the rest of a burst and return undefined for suppressed calls.
  • Never make a trailing call once the burst ends.
  • Restart the cooldown on every call, so a steady stream of calls closer together than wait only ever fires once.
  • Invoke fn again on the first call after a full wait of silence.

Notes

  • Let the timer handle double duty: null means "next call fires"; a non-null handle means "cooling down". Every call clears the old timer and sets a new one.
  • Opposite of trailing debounce: leading fires early then goes quiet; trailing waits for quiet then fires. Pick leading for buttons, trailing for search boxes.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +250 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.