throttleCancelable function

CancelableCallback throttleCancelable(
  1. VoidCallback fn,
  2. Duration interval
)

Like throttle, but returns a CancelableCallback so a pending trailing invocation can be dropped via CancelableCallback.cancel — call it on dispose so fn never fires after teardown and the Timer does not leak. Audited: 2026-06-13

Implementation

CancelableCallback throttleCancelable(VoidCallback fn, Duration interval) {
  DateTime? lastCall;
  Timer? timer;
  return CancelableCallback(
    () {
      final DateTime now = DateTime.now();
      final last = lastCall;
      if (last == null || now.difference(last) >= interval) {
        lastCall = now; // ignore: avoid_unused_assignment - used on next invocation
        fn();
        return;
      }
      if (timer?.isActive ?? false) return;
      timer = Timer(interval, () {
        lastCall = DateTime.now();
        fn();
      });
    },
    () => timer?.cancel(),
  );
}