Digamos que você tenha uma função chamada myFunc que é chamado toda vez que você digita algo em um campo de entrada. Depois de passar pelos requisitos do seu projeto, você decide mudar a experiência.

Em vez disso, você quer myFunc para executar quando pelo menos 2 segundos se passaram desde a última vez em que você digitou algo.

É aqui que um rebote pode entrar em jogo. Em vez de passar myFunc para o ouvinte de evento, você passaria a rejeição. O debounce propriamente dito levaria myFunc como argumento, junto com o número 2000.

Agora, sempre que você clicar no botão, myFunc só será executado se tiver decorrido pelo menos 2 segundos antes da última vez myFunc foi chamado.

Como implementar uma função de rejeição

Do início ao fim, são necessárias apenas 14 linhas de código para implementar uma função de rejeição. O restante desta seção foca nessas 14 linhas de código, para que possamos ver como nossa função de debounce funciona internamente.

debounce(myFunction[function], delay[number])

1	let debounce(myFunction, delay){2   	let timeout;34     	return function() {5       	let context = this;6       	let args = arguments;7 8       	clearTimeout(timeout);9 10      	timeout = setTimeout(() => {11          	myFunction.apply(context, args);12       	}, delay)13  	}14	}

Começando na linha 1, declaramos uma nova função chamada rebater usando uma instrução de função. Esta nova função possui dois parâmetros, myFunction e demora.

1    let debounce(myFunction, delay) {23    }

Se você se lembra do nosso exemplo acima, myFunction é qualquer função que precise limitar o número de vezes que é executada.

demora é o tempo (em milissegundos) que precisa decorrer antes de myFunction pode executar novamente.

1    let debounce(myFunction, delay) {2        let timeout;3    }

Na linha 2, estamos declarando uma variável não inicializada chamada tempo esgotado.
Essa nova variável contém o timeoutID retornou quando chamamos setTimeout mais tarde em nossa função de debounce.

1    let debounce(myFunction, delay) {2        let timeout;3        4        return function() {5        }6    }

Na linha 4, estamos retornando uma função anônima. Esta função anônima será fechada sobre o tempo esgotado variável para que possamos manter o acesso a ela mesmo após a chamada inicial para rebater concluiu a execução.

Um fechamento no JavaScript ocorre sempre que uma função interna retém acesso ao escopo lexical de sua função externa, mesmo que a função externa tenha terminado de executar. Se você quiser saber mais sobre fechamentos, leia Capítulo 7 de “Você não conhece JS” por Kyle Simpson

1    let debounce(myFunction, delay) {2        let timeout;3        4        return function() {5            let context = this;6        }7    }

Na linha 5, estamos declarando uma nova variável inicializada denominada contexto com o valor de isto.

A palavra-chave ‘this’ em JavaScript opera de maneira diferente do que em outras linguagens de programação. O que ‘this’ aponta também depende de como é chamada a função em que ‘this’ está sendo usado.

Você pode aprender mais sobre a palavra-chave ‘this’ lendo este artigo.

1    let debounce(myFunction, delay) {2        let timeout;3        4        return function() {5            let context = this;6            let args = arguments;7        }8    }

Na linha 6, estamos declarando outra variável inicializada chamada args com um valor de argumentos.

A palavra-chave ‘argumentos’ em JavaScript é um objeto que opera como uma matriz. ‘argumentos’ contém os argumentos passados ​​para a função em que está sendo usada.

Você pode aprender mais sobre o objeto ‘argumentos’ lendo este artigo.

1    let debounce(myFunction, delay) {2        let timeout;3        4        return function() {5            let context = this;6            let args = arguments;78            clearTimeout(timeout);9        }10   }

Na linha 8, estamos chamando o clearTimeout método do WindowOrWorkerGlobalScope mixin. Isso garantirá que cada vez que chamamos nossa função de devolução, tempo esgotado é redefinido e o contador pode iniciar novamente.

A combinação de JavaScript ‘WindowOrWorkerGlobalScope’ nos dá acesso a alguns métodos conhecidos, como setTimeout, clearTimeout, setInterval, clearInterval e busca.

Você pode aprender mais sobre isso lendo este artigo.

1	let debounce(myFunction, delay){2   	let timeout;34     	return function() {5       	let context = this;6       	let args = arguments;7 8       	clearTimeout(timeout);9 10      	timeout = setTimeout(() => {11          	myFunction.apply(context, args);12       	}, delay)13  	}14	}

Nas linhas 10-12, chegamos ao final de nossa implementação da função de debounce.

A partir da linha 10, estamos realizando duas ações. A primeira ação é atribuir um valor ao tempo esgotado variável que declaramos na linha 2. O valor é um timeoutID que é retornado quando chamamos setTimeout na linha 10. Isso nos permitirá fazer referência ao tempo limite criado chamando setTimeout para que possamos redefini-lo sempre que nossa função de rejeição for usada.

A segunda ação executada está chamando setTimeout. Isso criará um tempo limite que será executado myFunction (o argumento da função passado para a nossa função de debounce) uma vez demora (o argumento numérico passado para nossa função de debounce) expirou.

Na linha 11, estamos chamando myFunc usando o Aplique método do objeto global Function. Como estamos usando um tempo limite, myFunc só será executado se permitirmos que o tempo limite atinja 0.

É aqui que o coração da nossa função de debounce entra em jogo, pois estamos redefinindo o tempo limite cada vez que o debounce é chamado. É isso que nos permite limitar a taxa de execução de myFunc.

O método ‘apply’ em JavaScript permite chamar uma função com um determinado valor ‘this’. Usando ‘apply’, podemos garantir o que ‘this’ faz referência.

Finalmente, na linha 12, estamos passando demora.

As linhas 13 e 14 contêm apenas colchetes, por isso não vamos examiná-las.

É isso aí. É assim que nossa função de debounce funciona internamente. Agora, vamos adicionar nosso exemplo anterior desde o início. Vamos criar um campo de entrada e anexar um ouvinte de eventos com a nossa função debounce como um de seus argumentos.

Exemplo do mundo real

Primeiro, precisamos criar um campo de entrada.

Em seguida, precisamos criar uma função que queremos executar sempre que digitarmos algo em nosso campo de entrada.

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

Finalmente, precisamos selecionar o campo de entrada que criamos acima e anexar um ouvinte de evento ‘keyup’ a ele.

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

Isso conclui o nosso exemplo do mundo real! Cada vez que digitamos algo em nosso campo de entrada, Olá Mundo será executado se pelo menos 2 segundos se passaram desde a última vez em que digitamos algo.

Notas de encerramento

As funções de rejeição são funções simples, mas poderosas, que podem ter um impacto perceptível na maioria dos aplicativos JavaScript.

Embora nosso exemplo tenha sido divertido e direto, muitas organizações grandes usam funções de rejeição para aumentar o desempenho de seus aplicativos.

Se você quiser saber mais sobre JavaScript, consulte o meu site! Eu estou trabalhando em algumas coisas legais em https://juanmvega.com.