What I Learned Today 💡 June 13, 2017

Higher-Order Functions for Event-Listener efficiency: throttle() and debounce()

Often in your web apps, you add event-listeners for various DOM Events. However, some of these DOM Events fire at a very fast rate. Examples include mousemove , resize , and scroll — all of these fire very rapidly.

If your event-handlers for these “spammy” events are computationally expensive, this may lead to poor performance. At worst, this provides a bad experience for the end-user. At best, this causes unease in the minds of developers for unnecessarily eating up computational power. In any case, there must be a better way.

Enter throttle() and debounce() .

Both of these are “wrappers” around your event-handlers that restrict how often they will execute, but they do it in different ways.

throttle()

throttle() restricts a function to only executing N number of times over a given time-period T.

Here is an example:

I have the following function, sayHello() :

const sayHello = () => console.log('hello!');

I will attach it as an event-handler to mousemove , but I only want it to execute a maximum of 3 times every 2 seconds.

This is what that would look like:

Here is the implementation:

debounce()

debounce() restricts function execution in the following manner:

The given function shall execute only when it has not been invoked for T time.

Here is the ELI5 version:

The given function will only execute if you are patient. If you attempt to invoke the function before T time has passed, the execution-timer will reset. You will be forced to wait for the entire interval again.

Here is an example:

I will attach sayHello() as an event-handler to mousemove , but I only want it to execute when it has not been invoked for 0.5 seconds.

This is what that would look like:

Notice that sayHello() doesn’t fire until I’ve waited 0.5 seconds without moving my mouse.

Here is the implementation:

Comparison

Here is a comparison between the three methods of event-handling:

Normal

Throttled

Debounced

Normal

Throttled

Debounced

Bonus: once()

There’s another higher-order function, once() , I came across that’s bound to be useful. It doesn’t quite fit with the DOM-Event efficiency theme that debounce() and throttle() have, but I thought I’d include it here anyway.

It’s a simple “wrapper” that only lets your function execute once, hence the name.

Here is an example:

Here is the implementation:

Opinions expressed in these articles do not reflect those of my employer.