Implement throttle
Write throttle(fn, wait) that returns a throttled version of fn which runs at most once every wait ms:
- the first call runs
fnimmediately (the leading call) - calls made during the wait are held back; when the wait ends,
fnruns once more with the latest arguments andthis(the trailing call) - a trailing call starts a new wait of its own, so
fnnever runs twice withinwaitms - if a whole wait passes without any calls, the throttle resets and the next call runs immediately again
Example with wait = 100: t(1) at 0ms runs fn(1) right away; t(2) at 20ms and t(3) at 50ms are held back; at 100ms fn(3) runs, and fn(2) is never called.
Define throttle in the editor. 7 tests will call it.
Hint 1Use a timer variable to know whether you are inside a wait window. If there's no timer, call fn now and start one.
Hint 2If a timer is already running, don't call fn; just remember the latest args and this.
Hint 3When the timer fires: if something was saved, call fn with it and start another timer (a new window). If nothing was saved, clear the timer so the next call is a leading call again.
one clean solution
function throttle(fn, wait) {
let timer = null;
let pendingArgs = null;
let pendingThis = null;
function startWait() {
timer = setTimeout(() => {
if (pendingArgs) {
fn.apply(pendingThis, pendingArgs);
pendingArgs = pendingThis = null;
startWait(); // the trailing call opens a new window
} else {
timer = null;
}
}, wait);
}
return function throttled(...args) {
if (timer === null) {
fn.apply(this, args);
startWait();
} else {
pendingArgs = args;
pendingThis = this;
}
};
}