debounce

Retrasa la llamada a una función hasta que pasa wait desde la última llamada — de una ráfaga solo sobrevive la última.

Debounced<T> debounce<T>(void Function(T arg) func, Duration wait, {bool leading = false}) class Debounced<T> { void call(T arg); // Debounced is callable: debounced(arg) void cancel(); } FxEvents<T> FxEvents<T>.debounce(Duration window) // chain (events) Debounced<T> (void Function(T arg)).fxDebounce(Duration wait, {bool leading = false}) // method

Lección

debounce envuelve un callback para que las llamadas repetidas en rápida sucesión se colapsen en una sola. Cada llamada reinicia un temporizador de duración wait; la función func envuelta solo se dispara de verdad cuando pasa wait sin otra llamada — y lo hace con el argumento que recibió esa última llamada. Es el patrón clásico de «espera a que el usuario deje de teclear antes de buscar».

En JS, FxTS engancha un método .cancel() directamente a la función devuelta. Las funciones de Dart no pueden llevar miembros extra, así que FxDart devuelve un Debounced<T> — una clase con un método call(T arg), que Dart te deja invocar con sintaxis normal de llamada a función (debounced(arg)) gracias a la convención call(), más un .cancel() explícito para descartar cualquier invocación pendiente.

Por defecto (leading: false) solo se dispara el flanco de bajada — la última llamada de la ráfaga, cuando todo se calma. Pasa leading: true y será la primera llamada de la ráfaga la que se dispare de inmediato, suprimiendo el resto hasta el siguiente periodo de calma.

Demo 1 · Flanco de bajada (el valor por defecto)

Tres llamadas rápidas se colapsan en una — solo sobrevive el último argumento:

Demo 2 · Flanco de subida y cancel()

leading: true dispara de inmediato y suprime el resto de la ráfaga; .cancel() descarta por completo una llamada de flanco de bajada pendiente:

La forma con método

El propio callback lleva lo mismo como método: saveDraft.fxDebounce(wait) es debounce(saveDraft, wait), argumentos con nombre incluidos.

void saveDraft(String text) => _post(text);

final save = saveDraft.fxDebounce(const Duration(milliseconds: 300));
save('h');
save('he');
save('hello');   // only this one reaches _post

El prefijo fx es deliberado: dice qué librería está envolviendo el callback y deja el nombre desnudo libre para lo que el proyecto quiera poner en sus tipos función — la misma convención que las formas con getter de fx.

Pruébalo tú

Ejercicio: envuelve save en debounce (100 ms de espera) para que solo sobreviva el valor final de la ráfaga de llamadas de abajo.

En streams de eventos

La misma idea existe en la capa de eventos: cuando lo que llega en ráfagas es un Stream y no un callback, fxEvents(s).debounce(window) emite el valor final de cada ráfaga una vez que pasa window sin un evento más nuevo — y un valor aún pendiente cuando el stream se cierra se emite al final, nunca se pierde. Consulta fxEvents para conocer la cadena a la que pertenece.

Relacionado: throttle — se dispara a intervalos regulares en lugar de tras la calma · delay & sleep — para montar demos con temporización · concurrent — limitar el ritmo de pipelines asíncronos · shuffle — aleatoriedad con semilla