Explicación del rebote: cómo hacer que su JavaScript espere a que el usuario termine de escribir

Las funciones antirrebote en JavaScript son funciones de orden superior que limitan la velocidad a la que se llama a otra función.

Una función de orden superior es una función que toma una función como argumento o devuelve una función como parte de su declaración de retorno. Nuestra función antirrebote hace ambas cosas.

El caso de uso más común para un rebote es pasarlo como un argumento a un detector de eventos adjunto a un elemento HTML. Para comprender mejor cómo se ve y por qué es útil, veamos un ejemplo.

Digamos que tiene una función nombrada myFuncque se llama cada vez que escribe algo en un campo de entrada. Después de revisar los requisitos de su proyecto, decide que desea cambiar la experiencia.

En cambio, desea myFuncejecutar cuando hayan pasado al menos 2 segundos desde la última vez que escribió algo.

Aquí es donde entra en juego una lata antirrebote. En lugar de pasar myFuncal detector de eventos, pasaría el antirrebote. El antirrebote en sí mismo tomaría entonces myFunccomo argumento, junto con el número 2000.

Ahora, siempre que haga clic en el botón, myFuncsolo se ejecutará si han transcurrido al menos 2 segundos antes de que myFuncse llamara la última vez .

Cómo implementar una función antirrebote

De principio a fin, solo se necesitan 7 líneas de código para implementar una función antirrebote. El resto de esta sección se centra en esas 7 líneas de código para que podamos ver cómo funciona internamente nuestra función antirrebote.

function debounce( callback, delay ) { let timeout; return function() { clearTimeout( timeout ); timeout = setTimeout( callback, delay ); } }

Comenzando con la línea 1, hemos declarado una nueva función llamada debounce. Esta nueva función tiene dos parámetros callbacky delay.

function debounce( callback, delay ) { } 

callback es cualquier función que necesite limitar el número de veces que se ejecuta.

delayes el tiempo (en milisegundos) que debe transcurrir antes de que se callbackpueda ejecutar de nuevo.

function debounce( callback, delay ) { let timeout; }

En la línea 2, declaramos una variable no inicializada llamada timeout.

Esta nueva variable contiene lo timeoutIDdevuelto cuando llamamos setTimeoutmás adelante en nuestra debouncefunción.

function debounce( callback, delay ) { let timeout; return function() { } }

En la línea 3, devolvemos una función anónima. Esta función anónima se cerrará sobre la timeoutvariable para que podamos retener el acceso a ella incluso después de que la llamada inicial a debouncehaya terminado de ejecutarse.

Un cierre en JavaScript ocurre siempre que una función interna retiene el acceso al ámbito léxico de su función externa, aunque la función externa haya terminado de ejecutarse. Si desea obtener más información sobre los cierres, puede leer el Capítulo 7 de "No conoce JS" de Kyle Simpson
function debounce( callback, delay ) { let timeout; return function() { clearTimeout( timeout ); } }

En la línea 4, llamamos al clearTimeoutmétodo del WindowOrWorkerGlobalScopemixin. Esto asegurará que cada vez que llamemos a nuestra debouncefunción, timeoutse reinicie y el contador pueda comenzar de nuevo.

El WindowOrWorkerGlobalScopemixin de JavaScript nos da acceso a algunos métodos conocidos, como setTimeout, clearTimeout, setInterval, clearInterval, y fetch.

Puede obtener más información al respecto leyendo este artículo.

function debounce( callback, delay ) { let timeout; return function() { clearTimeout( timeout ); timeout = setTimeout( callback, delay ); } }

En la línea 5, llegamos al final de la debounceimplementación de nuestra función.

Esa línea de código hace algunas cosas. La primera acción es asignar un valor a la timeoutvariable que declaramos en la línea 2. El valor es un timeoutIDque se devuelve cuando llamamos setTimeout. Esto nos permitirá hacer referencia al tiempo de espera creado al llamar setTimeoutpara que podamos restablecerlo cada vez debounceque se use nuestra función.

La segunda acción realizada es llamar setTimeout. Esto creará un tiempo de espera que se ejecutará callback(el argumento de función pasado a nuestra debouncefunción) una vez delay(el argumento de número pasado a nuestra debouncefunción) haya transcurrido.

Como estamos usando un tiempo de espera, callbacksolo se ejecutará si permitimos que el tiempo de espera llegue a 0. Aquí es donde debounceentra en juego el corazón de nuestra función, ya que estamos restableciendo el tiempo de espera cada vez que debouncese llama. Esto es lo que nos permite limitar la tasa de ejecución de myFunc.

Las líneas 5 y 6 contienen solo corchetes, por lo que no las repasaremos.

Eso es. Así es como debouncefunciona nuestra función internamente. Ahora agreguemos a nuestro ejemplo anterior desde el principio. Vamos a crear un campo de entrada y adjuntar un detector de eventos con nuestra debouncefunción como uno de sus argumentos.

Ejemplo del mundo real

Primero, necesitamos crear un campo de entrada.

Type something in! 

A continuación, necesitamos crear una función que queramos ejecutar cada vez que escribimos algo en nuestro campo de entrada.

function helloWorld() { console.log("Hello World!") }

Finalmente, debemos seleccionar el campo de entrada que creamos arriba y adjuntarle un keyupdetector de eventos.

const myInput = document.getElementById("myInput"); myInput.addEventListener( "keyup", debounce( helloWorld, 2000 ) );

¡Eso concluye nuestro ejemplo del mundo real! Cada vez que escribimos algo en nuestro campo de entrada, helloWorldse ejecutará si han pasado al menos 2 segundos desde la última vez que escribimos algo.

Un agradecimiento especial al usuario de Reddit stratoscope por ayudar a corregir parte del código inicial de este artículo. Aquí hay una demostración funcional que creó de esta debouncefunción en Repl.it.

Notas de cierre

Las funciones de supresión de rebotes son funciones simples, pero potentes, que pueden tener un impacto notable en la mayoría de las aplicaciones JavaScript.

Si bien nuestro ejemplo fue divertido y sencillo, muchas organizaciones grandes utilizan funciones antirrebote para aumentar el rendimiento de sus aplicaciones.

If you want to learn more about JavaScript, check out my website! I am working on some cool stuff at //juanmvega.com.