debounce method

Stream<T> debounce(
  1. Duration duration
)

Suppresses events that arrive within duration of each other, emitting only the last one in each quiet window (debounce).

Implementation

Stream<T> debounce(Duration duration) {
  late StreamController<T> controller;
  StreamSubscription<T>? subscription;
  Timer? timer;
  T? latest;
  var hasLatest = false;
  var sourceDone = false;

  void emitLatest() {
    if (hasLatest) {
      controller.add(latest as T);
      latest = null;
      hasLatest = false;
    }
    if (sourceDone) {
      unawaited(controller.close());
    }
  }

  void listenToSource() {
    subscription = listen(
      (value) {
        latest = value;
        hasLatest = true;
        timer?.cancel();
        timer = Timer(duration, emitLatest);
      },
      onError: controller.addError,
      onDone: () {
        sourceDone = true;
        timer?.cancel();
        emitLatest();
      },
    );
  }

  Future<void> cancel() async {
    timer?.cancel();
    latest = null;
    hasLatest = false;
    await subscription?.cancel();
  }

  controller =
      isBroadcast
          ? StreamController<T>.broadcast(onListen: listenToSource, onCancel: cancel)
          : StreamController<T>(onListen: listenToSource, onCancel: cancel);
  return controller.stream;
}