Executando verificação de segurança...
17

Entenda a diferença entre Throttle e Debounce (de forma visual e interativa)

Como programadores, eventualmente nos deparamos com uma situação em que um evento ocorre muitas vezes e acaba deixando o processamento desnecessariamente lento. Por exemplo, imagine uma situação onde você precisa criar um formulário com salvamento automático, então resolve salvar sempre que o usuário pressiona uma tecla; ou que você precise redesenhar tudo o que está na tela quando o usuário redimensionar a janela. Realizar essas ações sempre que os eventos acontecem pode ser bem custoso.

Então, você descobre duas coisas que podem te ajudar: debounce e throttle. Elas acabam sendo tão "parecidas" que existem vários artigos sobre a diferença entre as duas, e no começo é normal esquecer e precisar pesquisar "debounce vs throttle" para relembrar o que é cada coisa.

  • Função comum: A função é chamada sempre que o evento (gatilho) ocorre.
  • Debounce: Uma função "debounced" é chamada após um período de tempo N desde sua última chamada. Ou seja, se o período definido for 1 segundo, não importa quantos eventos ocorrerem, a função será chamada novamente apenas caso fique 1 segundo sem receber o evento.
  • Throttle: O throttle serve para reduzir o número de vezes que uma ação pode ser chamada em um determinado período de tempo N. Se seguirmos o exemplo de um período de 1 segundo, isso significa que a função só será chamada novamente após pelo menos 1 segundo ter passado, caso o evento ocorra novamente.

Talvez eu não tenha conseguido explicar bem, mas a verdade é que é realmente difícil entender sem um exemplo prático, ou sem uma explicação visual ou interativa. É por isso que resolvi trazer um artigo para cá: Debounce vs Throttle: Definitive Visual Guide. A animação não funciona bem no Firefox, então se você estiver num navegador que parece "esquisito", experimente acessar o site pelo Chrome.

Função comum

O exemplo disponibilizado no site é uma máquina que libera uma bolinha sempre que um botão é pressionado. Quer dizer, este é o exemplo para uma "função comum". Veja abaixo e preste atenção (neste e nos próximos exemplos) na contagem "Button clicked" e "Event handler called":

A cada vez que o botão é pressionado, a máquina libera uma bolinha.

Throttle

Agora, se o botão da máquina funcionar com throttle, como fica? Bom, vamos imaginar que o tempo do throttle seja de 500ms. Isso significa que, se você pressionar o botão a cada 300ms, uma bolinha será liberada a cada clique após os 500ms. Ou seja, a função só será executada novamente após, pelo menos, 500ms. Por exemplo:

  • Clique 1 (0ms): Libera bolinha.
  • Clique 2 (300ms): Não libera.
  • Clique 3 (600ms): Libera bolinha.
  • Clique 4 (900ms): Não libera.

Veja um exemplo visual pelo site, com cliques sem um intervalo bem definido entre eles:

Mesmo que o botão seja pressionado várias vezes, a máquina só libera uma bolinha após esperar pelo menos 500ms

Debounce

No caso do debounce, a máquina irá liberar a bolinha apenas após ficar N milésimos de segundo sem ser pressionada. Ou seja, se o tempo for 500ms e você pressionar a cada 300ms, não terá nenhuma bolinha até parar de pressionar. No exemplo do artigo, a função debounce não é executada inicialmente, diferentemente da throttle, então fica assim:

  • Clique 1 (0ms): Não libera bolinha.
  • Clique 2 (300ms): Não libera.
  • Clique 3 (600ms): Não libera.
  • Clique 4 (900ms): Não libera.
  • (1400ms): Libera bolinha.

No exemplo acima, o clique 4 foi o gatilho que liberou a bolinha porque não teve outro clique durante os próximos 500ms (entre o tempo 900ms e o 1400ms), mas a bolinha surgiu apenas 500ms após o clique.

Veja agora um exemplo com a máquina do site, novamente com cliques sem um intervalo bem definido entre eles:

A máquina só libera uma bolinha após ficar 500ms sem o botão ser pressionado.

Agora uma curiosidade aplicada ao mundo real: se o interruptor de luz tivesse um debounce imbutido, nenhuma criança (ou adulto) conseguiria brincar de ficar acendendo e apagando a luz rápido 😅

Em algumas situações, pode ser útil mudar o comportamento do debounce para a função ser executada na primeira tentativa.


Espero que esse site sirva de referência rápida para vocês como serviu para mim, quando estava começando a trabalhar com frontend e precisei lidar com eventos gerados pelo usuário.