Índice del contenido

Debounce y Throttle en Javascript

Debounce y Throttle en Javascript

Debounce y throttle son patrones de diseño usados para limitar la ejecución de funciones, generalmente son utilizados para restringir la cantidad de veces que un evento se dispara: eventos click, scroll, resize u otros. Los patrones no son exclusivos de Javascript; en una entrada anterior te explique como usar throttle para limitar la cantidad de requests que recibe el servidor nginx.

Ambos patrones generan una función que recibe un callback y un tiempo de espera o delay.

Debounce

El patrón de rebote o debounce pospone la ejecución de una función hasta que transcurra un determinado tiempo de espera.

Nuevos intentos de ejecutar la función cancelarán la ejecución pendiente y reiniciarán el tiempo de espera.

Esquema simplificado del patrón debounce

Explicación de debounce

El código para debounce en javascript se ve así:

const debounce = (callback, tiempoDeEspera) => {
  let timeout 
  return (...args) => {
	clearTimeout(timeout)
	timeout = setTimeout(()=> callback(...args), tiempoDeEspera)
  }
}

Nuestra función debounce retorna a su vez una función, la cual recibirá cualquier número de argumentos (…args).

Esta función usa un closure para acceder a la variable timeout. ¿Qué es timeout? timeout es una función setTimeout, que programa la ejecución de nuestro callback para su posterior ejecución.

Pero ahora presta atención al clearTimeout. Cada vez que llamemos a la función debounce se eliminará cualquier función programada, por lo que la única manera de que se ejecute nuestro callback es esperar el tiempo que le pasamos como argumento.

Throttle

El patrón throttle o aceleración establece un tiempo de espera durante el cual no se pueden llamar nuevamente más funciones. A diferencia del patrón bounce, el tiempo de espera no se reinicia si intentamos llamar nuevamente a la función.

Esquema simplificado del patrón throttling

Explicación de throttle

El código para throttle en javascript se ve así.

const throttle = (callback, delay) => {
  let timeout
  return (...args) => {
    if (timeout !== undefined) {
      return
    }

    timeout = setTimeout(() => {
      timeout = undefined
    }, delay)

    return callback(...args)
  }
}

La función throttle retorna una función que tendrá dos vertientes que dependen del estado de timeout:

  • timeout está definido: esto significa que ya hay programada una función para su ejecución, en este caso la función no hace nada, es decir, bloquea la ejecución de nuevas funciones por medio de un return vacio.
  • timeout no está definido: si timeout no está definido, creamos un setTimeout y la asignamos a la variable timeout. Esta función, una vez transcurrido su tiempo de ejecución, se eliminará a si misma de la variable timeout. Posteriormente, y para finalizar, ejecutamos la función callback.

Otros recursos sobre debounce y throttling

Eduardo Zepeda
Desarrollador web, entusiasta de los sistemas GNU/Linux y el Software Libre. Py, Ts y Go, pero abierto a otras opciones como el Rustaceanismo. Creo en las bondades de las criptodivisas más allá de la especulación monetaria.
Leer más