I am using flutter_bloc library.
In the bloc, the mapEventToState
method is an async*
function which returns Stream<BlocState>
.
From this function I am calling other async*
functions like this yield* _handleEvent(event)
In such method, I am calling some Future returns functions but in the Future then()
function it wont let me call other yield* functions.
Here is an example:
Stream<BlocState> mapEventToState(BlocEvent event) async*{
yield* _handlesEvent(event); //This calls to worker method
}
Stream<BlocState> _handleEvent(BlocEvent event) async* {
_repository.getData(event.id).then((response) async* { //Calling Future returned function
yield* _processResult(response); //This won't work
}).catchError((e) async* {
yield* _handleError(e); //This won't work either
});
Response response = await _repository.getData(event.id); //This do works but I want to use it like above, is it possible?
yield* _processResult(response); //This do works
}
The question is however, how to combine between Future and Stream in dart.
I could use await _repository.getData
which works. but then I won't catch the error.
await
is just syntactic sugar for .then()
, and putting await
in a try
-catch
block is syntactic sugar for using .catchError
. Things that you can do one way can be done with the other.
In your first version that uses .then()
/.catchError()
, your function doesn't return anything.
Your callbacks won't work because you're using yield*
in them, but you haven't specified the callbacks with sync*
or async*
. To avoid name collisions, the yield
keyword requires them (in the same way that await
requires a function use async
or async*
).
Here's a version that should work with .then()
and .catchError()
:
Stream<BlocState> _handleEvent(BlocEvent event) async* {
yield* await _repository.getData(event.id).then((response) async* {
yield* _processResult(response);
}).catchError((e) async* {
yield* _handleError(e);
});
}
Note that the callbacks don't need to use yield*
; they could just return their Stream
s directly:
Stream<BlocState> _handleEvent(BlocEvent event) async* {
yield* await _repository.getData(event.id).then((response) {
return _processResult(response);
}).catchError((e) {
return _handleError(e);
});
}
But (as everyone else has noted) using await
instead of the Future
API simplifies the whole thing (especially since we're already using await
anyway):
Stream<BlocState> _handleEvent(BlocEvent event) async* {
try
response = await _repository.getData(event.id);
yield* _processResult(response);
} catch (e) {
yield* _handleError(e);
}
}
See https://dartpad.dartlang.org/fc1ff92e461754bdb35b998e7fbb3406 for a runnable example.