As described in the Riverpod docs, a Riverpod provider can watch other providers to make a "processing pipeline".
I have something like this:
final prov = Provider<String>((ref){
final w1 = ref.watch(prov1);
final w2 = ref.watch(prov2);
final w3 = ref.watch(prov3);
final w4 = ref.watch(prov4);
final complex = expensiveFunction(w1,w2,w3,w4);
return complex;
});
prov1
to prov4
can be modified individually by various bits of UI
But some UI actions cause some or all of them to change in quick succession.
How can I debounce calls to expensiveFunction()
until none of w1
..w4
have changed for say 2 secs?
From this tweet of the author of the riverpod package, here is how you can do it:
/// An extension on [Ref] with helpful methods to add a debounce.
extension RefDebounceExtension on Ref {
/// Delays an execution by a bit such that if a dependency changes multiple
/// time rapidly, the rest of the code is only run once.
Future<void> debounce(Duration duration) {
final completer = Completer<void>();
final timer = Timer(duration, () {
if (!completer.isCompleted) completer.complete();
});
onDispose(() {
timer.cancel();
if (!completer.isCompleted) {
completer.completeError(StateError('Cancelled'));
}
});
return completer.future;
}
}
final prov = FutureProvider<String>((ref) async {
final w1 = ref.watch(prov1);
final w2 = ref.watch(prov2);
final w3 = ref.watch(prov3);
final w4 = ref.watch(prov4);
try {
await debounce(Duration(seconds: 2));
} on StateError {
return;
}
final complex = expensiveFunction(w1,w2,w3,w4);
return complex;
});