You can also implement your own debounce in vanilla JavaScript. A widely quoted article is David Walsh's article on function debouncing with underscore which includes the source code used by underscore in their implementation:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
The debounce function serves as a generator for the actual function you'd like to call, that way the state can be persisted inside of the closure like this:
// example function
let sayHello = (name) => console.log(`Hi ${name}`)
// generate a debounced version with a min time between calls of 2 seconds
let sayHelloDebounced = debounce(sayHello, 2000)
// call however you want
sayHelloDebounced('David')
Demo in Stack Snippets
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
let sayHello = (name) => console.log(`Hi ${name}`)
let sayHelloDebounced = debounce(sayHello, 2000)
sayHelloDebounced('David')
sayHelloDebounced('David')
sayHelloDebounced('David')
<!-- end snippet -->
Other Implementations