how to implement toFuture from AsyncState #198
-
is this correct? extension SignalAsyncStateExtensions<T> on ReadonlySignal<AsyncState<T>> {
Future<T> toFuture() async {
final completer = Completer<T>();
EffectCleanup? disposer;
completer.future.whenComplete(() {
disposer?.call();
}).ignore();
disposer = subscribe((value) {
if (value is AsyncData) {
completer.complete(value.requireValue);
} else if (value is AsyncError) {
completer.completeError(value.error!, value.stackTrace);
}
});
onDispose(() {
disposer?.call();
});
return completer.future;
}
}
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 13 replies
-
You aren't covering a few edge cases. Memory PressureCalling this multiple times will create new completer instances and subscriptions. You probably want cache the completer. EagernessSubscriptions are eager so the future will be completed immediately with the current value/error, you probably want to wait for the next value. Signal is disposed before a value is emitted.If this happens, the future will wait indefinitely. You should complete with an error or with the current value in the ondispose callback. |
Beta Was this translation helpful? Give feedback.
-
edit: after improvements extension SignalAsyncStateExtensions<T> on ReadonlySignal<AsyncState<T>> {
Future<T> toFuture() async {
Completer<T>? completer = Completer<T>();
// register disposers
EffectCleanup? disposer;
// when signal disposed before future finished
onDispose(() {
disposer?.call();
if (completer?.isCompleted == false) {
completer!.completeError('future not completed');
}
completer = null;
});
// when future finished and signal still alive
completer!.future.whenComplete(() {
disposer?.call();
completer = null;
}).ignore();
disposer = subscribe((value) => _toFuture(completer!, value));
return completer!.future;
}
static void _toFuture<T>(Completer<T> completer, AsyncState<T> value) {
if (value is AsyncData) {
completer.complete(value.requireValue);
} else if (value is AsyncError) {
completer.completeError(value.error!, value.stackTrace);
}
}
}
|
Beta Was this translation helpful? Give feedback.
edit: after improvements