javascript fundamentals
closurestimershigher-order-functions
Throttle
Implement a throttle utility that caps how often a function can run.
What it tests
The difference between throttle and debounce — the question interviewers actually care about. Debounce waits for silence; throttle guarantees a maximum rate. Scroll and resize handlers want throttle, search inputs want debounce.
The approach
A boolean in the closure acts as a gate. While it's raised, calls are dropped; a timer lowers it and runs the function:
function throttleFn(fn, delay) {
let flag = false;
return function (...args) {
if (flag) return;
flag = true;
setTimeout(() => {
flag = false;
fn(...args);
}, delay);
};
}Where it usually goes wrong
- Leading vs trailing edge. This variant fires on the trailing edge —
the first call is delayed by
delay. If the interviewer wants the first call to run immediately, invokefnbefore starting the timer. - Dropping the final call. Calls that arrive while the gate is up are discarded entirely. Lodash keeps the last one and runs it when the window closes; say out loud which behaviour you're implementing.
Full solution
1 file from src/folders/throttle.
index.jsx
import { useEffect } from "react";
function throttleFn(fn, delay) {
let flag = false;
return function (...args) {
if (flag) return;
flag = true;
setTimeout(() => {
flag = false;
fn(...args);
}, delay);
};
}
function someFn() {
console.log("hi there");
}
const throttleCall = throttleFn(someFn, 1000);
export function Throttle() {
function handleClick() {
throttleCall();
}
useEffect(() => {
handleClick();
}, []);
return <button className="rounded-4xl bg-amber-50">Throttle</button>;
}share this post