Las funciones de rebote (debounce) no se ejecutan al momento de su invocación. En lugar de eso, su ejecución es retrasada por un periodo predeterminado de tiempo. Si la misma función es invocada de nuevo, la ejecución previa es cancelada y el tiempo de espera se reinicia.

Aquí hay un corto vídeo dónde se muestra cómo hacer una función de rebote (en inglés):

Y aquí está el código fuente que se muestra en el vídeo:

Ahora veamos el código con más detalles.

Asume que tienes un botón definido de la siguiente manera:

<button id="myBtn">Click me</button>

Y en tu archivo JavaScript tienes algo parecido a esto:

document.getElementById('myBtn').addEventListener('click', () => {
  console.log('clicked');
})

Cada vez que hagas clic en el botón, verás el mensaje "click" en tu consola.

Agreguemos ahora una función de rebote a nuestro manejador de evento click:

document.getElementById('myBtn').addEventListener('click', debounce(() => {
  console.log('click');
}, 2000))

La función de rebote recibe dos párametros: callback y wait. El primero recibe la función que deseas ejecutar después de un periodo de tiempo, mientras que el segundo recibe el tiempo a esperar antes de ejecutar la función callback.

En el ejemplo de arriba, nuestra función callback simplemente es una función que ejecuta un console.log('click'); y wait representa 2000 milisegundos de espera.

Dado este escenario, definamos debounce:

function debounce(callback, wait) {
  let timerId;
  return (...args) => {
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      callback(...args);
    }, wait);
  };
}

La función debounce recibe dos parámetros: el callback (la función que queremos ejecutar luego de un periodo predeterminado) y el periodo de espera wait (después del cuál callback será ejecutado).

Dentro de la función debounce, simplemente retornamos otra función, así:

let timerId;
return (...args) => {
  clearTimeout(timerId);
  timerId = setTimeout(() => {
    callback(...args);
  }, wait);
};

El próposito de esta función es invocar a la función callback después de cierto período de tiempo. Si durante el periodo de espera la misma función es ejecutada nuevamente, la ejecución previa es cancelada y el temporizador es reiniciado para empezar de nuevo.

¡Eso es todo! Todo lo que necesitas saber sobre qué es una función de debounce.

Aquí hay un video extra que habla sobre closures, ya que en este ejemplo usé un closure dentro de mi función debounce.

Avísame en Twitter si pudiste encontrar el uso de closure dentro de la función debounce.

¡Feliz programación, a todos!

Traducido del artículo de Adeel Imran - Debounce JavaScript – How to Make your JS Wait Up