invalidatableFuture<T> method
A side effect that allows you to watch a future lazily (by invoking the first callback) that can be invalidated lazily (by invoking the second callback).
You supply a futureFactory
, which is a function that must
return a new instance of a future to be watched.
See also refreshableFuture, which eagerly refreshes futures.
Note: this returns an AsyncValue<T> Function()
because returning a
function enables this side effect to determine whether or not there is any
demand for the future itself, enabling it to be evaluated lazily.
Implementation
(AsyncValue<T> Function(), void Function()) invalidatableFuture<T>(
Future<T> Function() futureFactory,
) {
final runTxn = use.transactionRunner();
final (getAsyncState, setAsyncState) =
use.data<AsyncValue<T>>(AsyncLoading<T>(None<T>()));
final (getFutureCancel, setFutureCancel) = use.data<void Function()?>(null);
use.register((api) => api.registerDispose(() => getFutureCancel()?.call()));
return (
() {
if (getFutureCancel() == null) {
setAsyncState(AsyncLoading<T>(getAsyncState().data));
final subscription = futureFactory().asStream().listen(
(data) => setAsyncState(AsyncData(data)),
onError: (Object error, StackTrace trace) => setAsyncState(
AsyncError(error, trace, getAsyncState().data),
),
);
setFutureCancel(subscription.cancel);
}
return getAsyncState();
},
() {
runTxn(() {
getFutureCancel()?.call();
setFutureCancel(null);
});
},
);
}