throttle

Invoca una función como máximo una vez por periodo de espera — a un ritmo fijo, a diferencia del «esperar a que haya calma» de debounce.

Throttled<T> throttle<T>(void Function(T arg) func, Duration wait, {bool leading = true, bool trailing = true}) class Throttled<T> { void call(T arg); // Throttled is callable: throttled(arg) void cancel(); } FxEvents<T> FxEvents<T>.throttle(Duration window, {bool leading = true, bool trailing = false}) // chain (events) Throttled<T> (void Function(T arg)).fxThrottle(Duration wait, {bool leading = true, bool trailing = true}) // method

Lección

throttle garantiza que func se ejecute como máximo una vez cada wait, por muchas veces que se llame a la función con throttle. Esa es la diferencia clave con debounce: debounce reinicia su temporizador en cada llamada, así que un flujo continuo de llamadas puede retrasar la ejecución indefinidamente; la ventana de throttle es fija una vez arranca, así que las llamadas siguen pasando con una cadencia regular — útil para cosas como manejadores de scroll o resize, donde quieres actualizaciones periódicas y no solo una al final del todo.

Tanto leading como trailing valen true por defecto: la primera llamada de una ventana se dispara de inmediato (flanco de subida) y, si llegan más llamadas antes de que la ventana se cierre, la última se dispara al terminar la ventana (flanco de bajada, con el argumento más reciente). Desactiva cualquiera de los dos para obtener un comportamiento solo-leading o solo-trailing. Igual que debounce, el Throttled<T> devuelto es una clase invocable con un .cancel() para descartar una llamada trailing pendiente.

Demo 1 · Leading + trailing (el valor por defecto)

La primera llamada se dispara de inmediato; la última de la ventana se dispara otra vez cuando la ventana se cierra:

Demo 2 · Ajustar leading/trailing, y cancel()

Desactiva leading para un comportamiento solo-trailing, desactiva trailing para solo-leading, o llama a .cancel() para descartar una llamada trailing pendiente:

La forma con método

Igual que debounce: onScroll.fxThrottle(wait) es throttle(onScroll, wait), y reenvía leading y trailing sin cambios.

void onScroll(double offset) => _measure(offset);

final handler = onScroll.fxThrottle(
  const Duration(milliseconds: 100),
  trailing: false,
);

El prefijo fx nombra a la librería que envuelve, la misma convención que las formas con getter de fx.

Pruébalo tú

Ejercicio: envuelve onClick en throttle (100 ms de espera) para que los clics rápidos se registren como mucho dos veces —leading y trailing— en lugar de tres veces por separado.

En streams de eventos

La misma idea existe en la capa de eventos: cuando lo que no calla es un Stream y no un callback, fxEvents(s).throttle(window, trailing: …) deja pasar un evento por ventana. Un valor por defecto cambia: la forma de stream es solo leading salvo que pases trailing: true (el wrapper de callback de arriba activa ambos flancos por defecto). Consulta fxEvents para conocer la cadena a la que pertenece.

Relacionado: debounce — espera a que haya calma en vez de seguir un ritmo fijo · delay & sleep — para construir demos con tiempos · shuffle — aleatoriedad con semilla · concurrent — limitación de tasa para pipelines asíncronos