, ,

5 Real-World Use Cases of Throttle Functions in JavaScript

Posted by

Stop your app from firing hundreds of events per second learn how throttling can make your code faster, smoother, and more efficient.

Stop your app from firing hundreds of events per second learn how throttling can make your code faster, smoother, and more efficient.

Introduction

If you’ve ever logged a scroll or resize event in JavaScript, you’ve probably seen this chaos:

window.addEventListener("scroll", () => console.log("Scrolling..."));

Now open the console and scroll hundreds of logs per second! 😬

That’s because scroll, resize, mousemove, and other browser events fire dozens (sometimes hundreds) of times per second.
 Left unchecked, they can crash your UI or freeze animations.

The solution? Throttle functions.

A throttle ensures that a function runs at most once every X millisecondsno matter how many times it’s called.

This post will show you how throttling actually works and five real-world use cases where it can save your app from performance bottlenecks.


What Is Throttling?

Throttling means limiting the rate at which a function executes.

Visually:

Event stream: |--------|------|------|--------|-------|-------|---------|
Throttle: Run ✅ Skip Skip Run ✅ Skip Skip Run ✅

Instead of reacting to every single event, it reacts at regular intervals.

Think of it as:

“No matter how often you ask, I’ll only respond once every X milliseconds.”


Step 1: Writing a Simple Throttle Function

Let’s build it ourselves, no Lodash needed:

function throttle(fn, delay) {
let lastCall = 0;

return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn.apply(this, args);
}
};
}

✅ Executes immediately on first call
✅ Ignores calls until the delay passes


Use Case #1 Optimizing Scroll Events

Every pixel you scroll fires an event. That’s overkill if you’re updating a progress bar or triggering lazy loading.

const handleScroll = throttle(() => {
const scrollTop = window.scrollY;
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollPercent = (scrollTop / docHeight) * 100;
console.log("Scrolled:", scrollPercent.toFixed(2) + "%");
}, 200);

window.addEventListener("scroll", handleScroll);

✅ Updates every 200ms instead of 60+ times per second
✅ Keeps scrolling smoothly
✅ Saves CPU cycles and improves FPS

Real use:

  • Updating scroll progress bars
  • Triggering animations
  • Lazy loading sections

Use Case #2: Resizing the Window

The resize event fires continuously while dragging the window corner, and recalculating the layout each time can be expensive.

const handleResize = throttle(() => {
console.log("Window size:", window.innerWidth, "x", window.innerHeight);
}, 300);

window.addEventListener("resize", handleResize);

✅ Prevents layout recalculations with every pixel move
✅ Ideal for grid recalculations, chart resizing, or responsive layouts

Pro Tip: Pair throttling with requestAnimationFrame() For smoother animations:

function throttleRAF(fn) {
let running = false;
return function (...args) {
if (running) return;
running = true;
requestAnimationFrame(() => {
fn.apply(this, args);
running = false;
});
};
}

This version runs in sync with the browser’s paint loop.


Use Case #3 Infinite Scroll or Lazy Loading

When implementing infinite scrolling, you only want to trigger loading when the user is near the bottom, not on every scroll event.

const loadMore = () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100) {
console.log("Load more content...");
}
};

window.addEventListener("scroll", throttle(loadMore, 300));

✅ Prevents duplicate “load more” triggers
✅ Keeps scrolling smoothly
✅ Great for news feeds, product lists, or chat apps

Pro Tip: Combine with IntersectionObserver for even better results.


4️⃣ Use Case #4 Limiting API Calls or Event Streams

When connecting real-time inputs (like dragging sliders or moving a map), you might call an API or update a preview too frequently.

Example:

const updateLocation = throttle(async (coords) => {
await fetch("/api/update-location", {
method: "POST",
body: JSON.stringify(coords),
});
console.log("Sent:", coords);
}, 1000);

Attach this to a GPS listener or draggable map:

navigator.geolocation.watchPosition((pos) => {
const { latitude, longitude } = pos.coords;
updateLocation({ latitude, longitude });
});

✅ Prevents flooding the backend
✅ Keeps server usage predictable
✅ Useful for live tracking, IoT updates, or analytics batching


Use Case #5: Smoothing Animations and Mouse Move Events

When tracking mouse movement or animation updates, throttle keeps rendering stable and consistent.

const circle = document.querySelector(".circle");

const moveCircle = throttle((e) => {
circle.style.transform = `translate(${e.pageX}px, ${e.pageY}px)`;
}, 50);

window.addEventListener("mousemove", moveCircle);

Without throttle → choppy, CPU-heavy updates
 With throttle → buttery-smooth animations

Used in:

  • Canvas drawing tools
  • Drag-and-drop interfaces
  • Tooltip tracking

Bonus: Adding “Trailing Call” Support

The simple throttle above only triggers immediately.
 Let’s improve it to also run after the last call (like Lodash’s throttle).

function throttle(fn, delay) {
let lastCall = 0;
let timeout;

return function (...args) {
const now = Date.now();
const remaining = delay - (now - lastCall);

if (remaining <= 0) {
clearTimeout(timeout);
lastCall = now;
fn.apply(this, args);
} else if (!timeout) {
timeout = setTimeout(() => {
lastCall = Date.now();
timeout = null;
fn.apply(this, args);
}, remaining);
}
};
}

✅ Fires both immediately and at the end of rapid event bursts.
✅ Best of both worlds leading + trailing execution.


Debounce vs Throttle: Quick Recap

👉 In short:

  • Debounce waits for silence.
  • The throttle controls the volume. 🎚️

Common Gotchas

⚠️ Using wrong delays too short = useless, too long = laggy UX.
⚠️ Recreating throttled functions in React without useCallback.
⚠️ Forgetting context, always use fn.apply(this, args) inside.
⚠️ Combining with async operations, watch out for race conditions.


Why Throttling Matters in Modern Apps

Modern UIs rely on constant event streams: scrolling, resizing, dragging, and moving.
Without throttling, every event triggers calculations or network requests, killing your FPS and user experience.

Throttling makes your app feel stable and smooth. It’s invisible optimization, the kind that separates sluggish interfaces from premium ones.

✅ Reduces CPU & GPU load
✅ Smooths animations and scrolls
✅ Protects APIs from overuse
✅ Makes interactions feel polished


Conclusion

Throttle functions are one of the most underrated tools in a developer’s performance toolkit.

5 Real-World Uses Recap:

  1. Scroll event optimization
  2. Window resizing
  3. Infinite scroll / lazy loading
  4. API rate limiting
  5. Smooth mouse move animations

You don’t need Lodash, just a few lines of code and some understanding of timing.
 Once you learn to control how often your functions fire, your app feels instantly faster.

Throttle less, perform more.


Call to Action

Have you ever implemented throttling in your project or seen a performance issue that could’ve been fixed?
Share your experience in the comments 👇

And if your teammate’s scroll handler logs 200 times per second, send them this post. It’ll save their app (and your sanity).

One response

Leave a Reply

Your email address will not be published. Required fields are marked *