Diferença entre limitar e rebater uma função

250

Alguém pode me dar uma explicação em palavras simples sobre a diferença entre limitar e rebater uma função para fins de limitação de taxa.

Para mim, os dois parecem fazer o mesmo. Eu verifiquei esses dois blogs para descobrir:

http://remysharp.com/2010/07/21/throttling-function-calls

http://benalman.com/projects/jquery-throttle-debounce-plugin/

bhavya_w
fonte
102
demo.nimius.net/debounce_throttle é uma boa visualização
thriqon
4
@thriqon essa visualização é melhor que a minha descrição.
Donal
Sim, aquele me ajudou a entender este conceito, bem ... +1 para o autor original ;-)
thriqon
Exemplo muito simples que me ajudou a entender. jsfiddle.net/Voronar/sxjy25ew/1
Kirill A. Khalitov
1
Pode ver a visualização aqui também codepen.io/chriscoyier/pen/vOZNQV
trungk18

Respostas:

345

Para colocar em termos simples:

  • A aceleração atrasará a execução de uma função. Reduzirá as notificações de um evento que é disparado várias vezes.
  • A rejeição agrupará uma série de chamadas seqüenciais para uma função em uma única chamada para essa função. Ele garante que uma notificação seja feita para um evento que é disparado várias vezes.

Você pode ver visualmente a diferença aqui

Se você tem uma função que é chamada muito - por exemplo, quando um evento de redimensionamento ou movimentação do mouse ocorre, ela pode ser chamada várias vezes. Se você não quiser esse comportamento, poderá regulá- lo para que a função seja chamada em intervalos regulares. Debouncing significa que é chamado no final (ou no início) de vários eventos.

Donal
fonte
9
Acho que o link de visualização da thriqon mostra como funciona muito bem. Se você tem uma função que é chamada muito - por exemplo, quando um evento de redimensionamento ou movimentação do mouse ocorre, ela pode ser chamada várias vezes. Se você não quiser isso, poderá regulá-lo para que a função seja chamada em intervalos regulares. A rejeição significa que é chamada no final (ou no início) de várias chamadas.
Donal
10
@AdamM. Dê uma olhada na visualização aqui: demo.nimius.net/debounce_throttle
Donal
2
@AdamM. Não. Você pode visualizar isso movendo o mouse na demonstração e interrompendo o movimento do mouse de vez em quando. A barra de debounce "marcará" depois que você interromper todo o movimento do mouse, enquanto a barra de aceleração continuará "marcando" enquanto o mouse estiver em movimento, mas a uma taxa reduzida (acelerada).
21416 John Weisz
26
Eu absolutamente amo a visualização. Obrigado!
Sammi
4
O link é mais valioso do que as mil palavras
Finesse
148

Pessoalmente, achei o debounce mais difícil de compreender do que o acelerador .

Como ambas as funções ajudam a adiar e reduzir a taxa de alguma execução. Supondo que você esteja chamando funções decoradas retornadas por acelerador / debounce repetidamente ...

  • Regulador de pressão : a função original é chamada no máximo uma vez por período especificado.
  • Debounce : a função original será chamada depois que o chamador parar de chamar a função decorada após um período especificado .

Eu achei a última parte do debounce crucial para entender o objetivo que ele está tentando alcançar. Também achei que uma versão antiga da implementação do _.debounce ajuda a entender (cortesia de https://davidwalsh.name/function-debounce ).

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

Uma metáfora absurda, mas talvez também possa ajudar.

Você tem um amigo chamado Chatty que gosta de conversar com você via IM. Supondo que, quando ela fala, ela envia uma nova mensagem a cada 5 segundos, enquanto o ícone do seu aplicativo de IM está pulando para cima e para baixo, você pode ...

  • Abordagem ingênua : verifique todas as mensagens desde que cheguem. Quando o ícone do seu aplicativo saltar, verifique. Não é a maneira mais eficaz, mas você está sempre atualizado.
  • Abordagem do acelerador : você verifica uma vez a cada 5 minutos (quando houver novos). Quando chegar uma nova mensagem, se você tiver verificado a qualquer momento nos últimos 5 minutos, ignore-a. Você economiza seu tempo com essa abordagem, enquanto ainda está em loop.
  • Abordagem de rebate : você conhece Chatty, ela divide toda a história em pedaços, envia-os em uma mensagem após a outra. Você espera até Chatty terminar a história toda: se ela parar de enviar mensagens por 5 minutos, você presumiria que ela terminou, agora você verifica todas.
Dapeng Li
fonte
17
Não entendi a diferença entre essas duas funções até ler isso. Obrigado
Seamus Barrett
7
A metáfora é uma das maiores peças de exemplo que eu já li sobre acelerador e debounce. Obrigado.
Vignesh
96

Diferenças

+--------------+-------------------+-------------------+
|              |  Throttle 1 sec   |  Debounce 1 sec   |
+--------------+-------------------+-------------------+
| Delay        | no delay          | 1 sec delay       |
|              |                   |                   |
| Emits new if | last was emitted  | there is no input |
|              | before 1 sec      |  in last 1 sec    |
+--------------+-------------------+-------------------+

Explicação por caso de uso :

  • Barra de pesquisa - não deseja pesquisar sempre que o usuário pressionar a tecla? Deseja pesquisar quando o usuário parou de digitar por 1 segundo. Use debounce1 segundo ao pressionar a tecla.

  • Jogo de tiro - A pistola demora 1 s entre cada tiro, mas o usuário clica no mouse várias vezes. Use throttleno clique do mouse.

Invertendo seus papéis :

  • Limitação de 1 segundo na barra de pesquisa - se os usuários digitarem abcdefghijcom todos os caracteres 0.6 sec. O acelerador será acionado na primeira apressão. Irá ignorar cada pressão nos próximos 1 segundo, ou seja, bem 0,6 seg. Será ignorado. Então, ca 1,2 s será acionado novamente, o que redefine a hora novamente. Portanto d, será ignorado e eserá acionado.

  • Revolver a pistola por 1 s - Quando o usuário vê um inimigo, ele clica no mouse, mas ele não atira. Ele clicará novamente várias vezes naquele segundo, mas não disparará. Ele vai ver se ele ainda possui balas, naquele momento (1 segundo após o último clique) a pistola dispara automaticamente.

amit77309
fonte
37

A otimização aplica um número máximo de vezes que uma função pode ser chamada ao longo do tempo. Como em "execute esta função no máximo uma vez a cada 100 milissegundos".

A depuração impõe que uma função não seja chamada novamente até que um certo período de tempo tenha passado sem que ela seja chamada. Como em "execute esta função somente se 100 milissegundos se passaram sem que ela seja chamada".

ref

Anshul
fonte
20

Regulador de pressão (1 s): Olá, sou um robô. Enquanto você continuar me pingando, continuarei falando com você, mas depois de exatamente 1 segundo cada. Se você me enviar uma resposta antes que um segundo se esgote, continuarei respondendo a você exatamente em 1 segundo. Em outras palavras, adoro responder em intervalos exatos.

Debounce (1 s): Olá, sou o primo do robô ^^. Enquanto você continuar me enviando um ping, continuarei em silêncio, porque eu gostaria de responder apenas depois de 1 segundo desde a última vez que você me enviou um ping . Não sei, se é porque tenho um problema de atitude ou porque simplesmente não gosto de interromper as pessoas. Em outras palavras, se você continuar me pedindo respostas antes de decorrido 1 segundo desde a sua última chamada, nunca receberá uma resposta. Sim, sim ... vá em frente! me chame de rude.


Regulador de pressão (10 min): Eu sou uma máquina de registro. Eu envio logs do sistema para o servidor back-end, após um intervalo regular de 10 minutos.

Debounce (10 s): Olá, eu não sou primo dessa máquina de registro. (Nem todo debouncer está relacionado a um regulador de pressão neste mundo imaginário). Eu trabalho como garçom em um restaurante próximo. Devo informar que, enquanto continuar adicionando coisas ao seu pedido, não irei à cozinha para executar seu pedido. Somente depois de decorridos 10 segundos após a última modificação do seu pedido, assumirei que você terminou o pedido. Só então executarei seu pedido na cozinha.


Demonstrações legais: https://css-tricks.com/debouncing-throttling-explained-examples/

Créditos para a analogia do garçom: https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf

Usman
fonte
1
melhor explicação.
Karan Sharma
17

A rejeição permite gerenciar a frequência das chamadas que uma função pode receber. Ele combina várias chamadas que acontecem em uma determinada função para que as chamadas repetidas que ocorrem antes da expiração de um período de tempo específico sejam ignoradas. Basicamente, a rejeição garante que exatamente um sinal seja enviado para um evento que pode estar acontecendo várias vezes.

A limitação restringe a frequência de chamadas que uma função recebe por um intervalo de tempo fixo. É usado para garantir que a função de destino não seja chamada com mais frequência que o atraso especificado. A limitação é a redução na taxa de um evento repetido.

GibboK
fonte
17

É simples.

Eles fazem exatamente a mesma coisa (limitação de taxa), exceto enquanto o acelerador é chamado, ele dispara sua função empacotada periodicamente e o debounce não. Debounce apenas (tenta) chamar sua função uma vez no final.

Exemplo : se você estiver rolando, o acelerador chamará sua função lentamente enquanto você rola (a cada X milissegundos). O Debounce esperará até depois de terminar a rolagem para chamar sua função.

Ryan Taylor
fonte
é importante notar que nessas demos, elas podem não parecer "idênticas" porque o debounce sempre dispara X milissegundos após o último evento, enquanto a última chamada do acelerador pode acontecer mais cedo (e não precisa ser chamada novamente quando o debounce normalmente dispara ) é bastante inconseqüente, mas vale a pena mencionar se você olhar para as demos.
Ryan Taylor
16

Em termos leigos:

A rejeição impedirá que uma função seja executada enquanto ainda estiver sendo chamada com freqüência. Uma função rejeitada será executada somente depois de ter sido determinado que não está mais sendo chamada e, nesse ponto, será executada exatamente uma vez. Exemplos práticos de devolução:

  • Salvamento automático ou validação do conteúdo de um campo de texto se o usuário "parou de digitar": a operação será realizada apenas uma vez, APÓS ter sido determinado que o usuário não está mais digitando (não pressionando mais as teclas).

  • Registrando onde os usuários pousam o mouse: o usuário não está mais movendo o mouse, para que a (última) posição possa ser registrada.

A limitação simplesmente impedirá que uma função seja executada se executada recentemente, independentemente da frequência da chamada. Exemplos práticos de limitação:

  • As implementações do v-sync são baseadas na limitação: a tela será desenhada apenas se tiverem decorrido 16ms desde o último sorteio da tela. Não importa quantas vezes a funcionalidade de atualização de tela seja chamada, ela será executada no máximo uma vez a cada 16ms.
John Weisz
fonte
7

Uma analogia da vida real que pessoalmente me ajuda a lembrar:

  • debounce = uma conversa . você espera a outra pessoa terminar de falar antes de responder.
  • acelerador = um bit de bateria . você só toca notas em uma simples bateria de 4/4.

Casos de uso para rejeição :

  • Digitando. Você deseja fazer algo depois que o usuário parou de digitar. Portanto, esperar 1 segundo após a última tecla faz sentido. Cada pressionamento de tecla reinicia a espera.
  • Animação. Você deseja reduzir um elemento depois que o usuário parou de passar o mouse sobre ele. Não usar debounce pode causar uma animação irregular, como resultado do movimento acidental do cursor entre as zonas "quente" e "fria".

Casos de uso para aceleração :

  • Rolagem. Você deseja reagir à rolagem, mas limitar a quantidade de cálculos feitos; portanto, fazer algo a cada 100 ms é suficiente para evitar um atraso em potencial.
  • Movimento do mouse. O mesmo que a rolagem, mas para mover o mouse.
  • Chamadas de API Você deseja acionar uma chamada de API em determinados eventos da interface do usuário, mas deseja limitar o número de chamadas de API feitas para não sobrecarregar o servidor.
Cara
fonte
4

throtle é apenas um invólucro em torno debounce que torna debounce para chamar passou functionem algum período de tempo, se debounce atrasa uma chamada de função no período de tempo que é maior, então especificado no throtle .

Oleg Tsyba
fonte
2

Limitação

A otimização aplica um número máximo de vezes que uma função pode ser chamada de horas extras. Como em "execute esta função no máximo uma vez a cada 100 milissegundos". Digamos que, em circunstâncias normais, você chamaria essa função 1.000 vezes em 10 segundos. Se você o reduzir para apenas uma vez a cada 100 milissegundos, ele executará essa função apenas no máximo 100 vezes

(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls

Debouncing

A depuração impõe que uma função não seja chamada novamente até que um certo período de tempo tenha passado sem que ela seja chamada. Como em "execute esta função somente se 100 milissegundos se passaram sem que ela seja chamada".

Talvez uma função seja chamada 1.000 vezes em uma explosão rápida, dispersa por 3 segundos e depois deixe de ser chamada. Se você o tiver devolvido a 100 milissegundos, a função será acionada apenas uma vez, em 3,1 segundos, depois que a explosão terminar. Cada vez que a função é chamada durante o burst, ela redefine o timer de recuperação

fonte: - acelerador e debouncing

Bajran
fonte
2

Suponha que tenhamos uma função de retorno de chamada "cb" a ser chamada no evento "E". Deixe "E" ser acionado 1000 vezes em 1 segundo; portanto, haverá 1000 chamadas para "cb". Isso é 1 chamada / ms. Para otimizar, podemos usar:

  • Limitação : Com a limitação de (100 ms), "cb" seria chamado em [100ª ms, 200ª ms, 300ª ms, ... 1000ª ms]. Isso é 1 chamada / 100 ms. Aqui, 1000 chamadas para "cb" são otimizadas para 10 chamadas.
  • Reembolsando : com a devolução de (100ms), "cb" seria chamado apenas uma vez em [1100seg]. Isso é 100ms após o último acionador de "E" que ocorreu em [1000th ms]. Aqui, 1000 chamadas para "cb" são otimizadas para 1 chamada.
National Geographic
fonte
1

Pelo que entendi, em termos simples Throttling - semelhante a chamar setInterval (retorno de chamada) por um certo número de vezes, ou seja, chamar a mesma função por certo número de vezes ao longo do tempo na ocorrência de evento e .. Debouncing - semelhante a chamar setTImeout (callbackForApi) ou chamar uma função após um certo tempo decorrido na ocorrência do evento. Este link pode ser útil- https://css-tricks.com/the-difference-between-throttling-and-debouncing/

Pranay Binju
fonte