- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript Throttle
JavaScript Performance
JavaScript Throttle
Throttling limits a function to running at most once in a given time window.
Debounce waits for calls to stop; throttle guarantees a steady trickle instead.
Scrolling is the classic case: you want updates, just not hundreds per second.
Example
Example
javascript
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
let calls = 0;
const throttled = throttle(function () { calls++; }, 10);
throttled();
throttled();
throttled();
console.log(calls);The output is 1: only the first of the three calls got through immediately.
How Throttle Works
The first call runs immediately.
Further calls are ignored until the interval has passed.
Unlike debounce, it guarantees regular execution, not just a final one.
Syntax
Syntax
javascript
const throttled = throttle(handleScroll, 100);100 milliseconds is a common interval for scroll handling.
The First Call Always Runs
This is the opposite of debounce, which waits before running at all.
Example
Example
javascript
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
let firstResult = null;
const throttled = throttle(function (value) { firstResult = value; }, 10);
throttled("immediate");
console.log(firstResult);The output is immediate, with no waiting.
Calls During the Interval Are Dropped
This keeps the rate steady, however fast the event actually fires.
Example
Example
javascript
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
let runs = 0;
const throttled = throttle(function () { runs++; }, 10);
for (let i = 0; i < 100; i++) {
throttled();
}
console.log(runs);One hundred rapid calls, and only the first one ran.
Scroll Handling
A scroll event can fire dozens of times a second without throttling.
Example
Example
javascript
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
let layoutChecks = 0;
const onScroll = throttle(function () { layoutChecks++; }, 10);
for (let i = 0; i < 50; i++) {
onScroll();
}
console.log(layoutChecks);Only one expensive layout check ran, not fifty.
Running Again After the Interval
Once the interval passes, the next call is allowed through.
Example
Example
javascript
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
function afterDelay(ms, callback) {
setTimeout(callback, ms);
}
let runs = 0;
const throttled = throttle(function () { runs++; }, 5);
throttled();
throttled();
afterDelay(15, function () {
throttled();
console.log(runs);
});The output is 2: the first call, then one more after the interval passed.
Debounce or Throttle?
Use debounce when only the final state matters, like search input.
Use throttle when you need steady updates throughout, like a progress indicator during scroll.
Example
Example
javascript
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
console.log(typeof throttle(function () {}, 100));Both return a wrapped function; the difference is entirely in when it runs.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Throttle</title>
<style>
#box { height: 150px; overflow-y: scroll; border: 1px solid #ccc; }
#content { height: 800px; }
</style>
</head>
<body>
<h1>Throttle</h1>
<div id="box"><div id="content"></div></div>
<p id="out">Scroll count: 0</p>
<script>
function throttle(fn, interval) {
let ready = true;
return function (...args) {
if (!ready) return;
ready = false;
fn(...args);
setTimeout(function () { ready = true; }, interval);
};
}
let count = 0;
const onScroll = throttle(function () {
count++;
document.getElementById("out").textContent = "Scroll count: " + count;
}, 200);
document.getElementById("box").addEventListener("scroll", onScroll);
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try scrolling fast:
Scroll the box quickly and see the count rise steadily rather than wildly.
Important Points
- Throttle allows at most one run per interval.
- The first call runs immediately, unlike debounce.
- Calls during the interval are simply dropped.
- Ideal for scroll and mouse-move handlers.
- Choose debounce for a final result, throttle for steady updates.
Conclusion
Throttle keeps a noisy event under control without losing responsiveness.
The first-call-runs-immediately behaviour is the key difference from debounce.
Both are small functions that solve a very common real problem.
