throttleWithScheduler<Time, Interval> method

Effect<Value> throttleWithScheduler<Time, Interval>({
  1. required EffectID id,
  2. required Interval interval,
  3. required Scheduler<Time, Interval> scheduler,
  4. required ThrottleDirection direction,
  5. required bool emitFirst,
})

Scheduler-aware throttle helper that allows custom timing via scheduler and fine-grained control over leading/trailing emission behavior.

Example:

final throttled = effect.throttleWithScheduler(
  id: "scroll",
  interval: const Duration(milliseconds: 100),
  scheduler: customScheduler,
  direction: ThrottleDirection.trailing,
  emitFirst: false,
);

Implementation

Effect<Value> throttleWithScheduler<Time, Interval>({
  required EffectID id,
  required Interval interval,
  required Scheduler<Time, Interval> scheduler,
  required ThrottleDirection direction,
  required bool emitFirst,
}) {
  return switch (this) {
    NoneEffect _ => this,
    _ => flatMap<Value>((value) {
        final lastThrottleTime = scheduler.getThrottleTimes(id);
        if (lastThrottleTime == null) {
          scheduler.setThrottleTimes(id, scheduler.now);
          return emitFirst || direction == ThrottleDirection.leading ? Effect.value(value) : Effect.none();
        } else {
          final (isGreater, remaining) = scheduler.distance(last: lastThrottleTime, interval: interval);

          switch (direction) {
            case ThrottleDirection.leading:
              if (isGreater) {
                scheduler.setThrottleTimes(id, scheduler.now);
                return Effect.value(value);
              } else {
                return Effect.none();
              }
            case ThrottleDirection.trailing:
              scheduler.setThrottleTimes(id, scheduler.now);
              return Effect.delayedWithScheduler(
                isGreater ? interval : remaining,
                () {
                  scheduler.setThrottleTimes(id, scheduler.now);
                  return value;
                },
                scheduler,
              );
          }
        }
      }).cancellable(id: id, cancelInFlight: true)
  };
}