Throttling Functions With Lodash's debounce() Function

Aug 13, 2019

Lodash's debounce() function lets you delay invoking a function until a certain number of milliseconds passes. One common use case for debounce() is HTTP API calls for autocompletes: suppose when the user is typing in an input, you only want to execute an HTTP request once. Below is a stubbed out example of how debounce() works.

const wait = 100;
el.addEventListener('change', _.debounce(autocomplete, wait));

el.value = 'te';
el.trigger('change'); // "Called: te" after 100ms
await new Promise(resolve => setTimeout(resolve, 110));

el.value = 'test';
// Nothing, because the next 'change' event takes over
el.trigger('change');
await new Promise(resolve => setTimeout(resolve, 50));

el.value = 'testing';
el.trigger('change'); // "Called: testing" after 100ms

function autocomplete() {
  console.log('Called:', el.value);
}

In practice, the autocomplete() function would make an HTTP request. With debounce(), the autocomplete() function would not get called until the user stopped typing for 100ms.

This blog post has a handy metaphor for debounce(): debounce() works like an elevator. The elevator doesn't leave until the door closes and the door stays open for at least 100ms. If another function call comes in, that's like someone holding the door open, and then the door waits another 100ms before closing.

There's also a maxWait option that the function will wait before executing. For example, if maxWait = 120, the 2nd 'change' event in the below example will execute after 60ms instead of 100ms.

const wait = 100;
el.addEventListener('change', _.debounce(autocomplete, wait, {
  maxWait: 120
}));

el.value = 'te';
el.trigger('change');
await new Promise(resolve => setTimeout(resolve, 60));

el.value = 'test';
el.trigger('change'); // "Called: test" after 60ms

function autocomplete() {
  console.log('Called:', el.value);
}

Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Lodash Tutorials