Reputation: 9579
Is it possible to somehow yield
to an outer scope?
Is there a more idiomatic approach that achieves the same intended result?
Stream<T> fetch() async* {
bool sentLiveValue = false;
Future<T> cached = cache.fetchValue();
cached.then((value) {
if (!sentLiveValue)
yield value; // Here, I want to yield to the outer scope.
});
await for (T value in liveValueSource.fetch()) {
yield value;
sentLiveValue = true;
cache.update(value);
}
}
If you're wondering about context, I'm implementing a data architecture with classes that can fetch
data.
The simplified code above should return a stream that first contains a cached value and then contains values from a live source.
Note that if the cache is slower than the live data source (which is possible if the cache doesn't contain a value yet), the live data should be used first. So await
ing the cache value is not an option.
Upvotes: 0
Views: 229
Reputation: 51722
One solution is to use a StreamController
, but beware: making your own streams is hazardous - you should handle listen, pause, resume and cancel.
A partial implementation is:
Stream<T> fetch<T>() {
var sentLiveValue = false;
var controller = StreamController<T>(
onListen: () {},
onPause: () {},
onResume: () {},
onCancel: () {},
);
cache.fetchValue().then((v) {
if (!sentLiveValue) {
controller.add(v);
}
});
liveValueSource.fetch().listen(
(t) {
sentLiveValue = true;
cache.update(t);
controller.add(t);
},
onDone: () => controller.close(),
onError: (e, st) => controller.addError(e, st),
);
return controller.stream;
}
Upvotes: 1