debounce method
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;
}