I had weird problem on which I spend few hours. I have a bloc file in which I'm using dartZ to easier maintain errors. When I was using bloc like this:
NumberTriviaBloc({required this.getConcreteNumberTrivia}) : super(Empty()) {
on<GetTriviaForConcreteNumber>((event, emit) async {
final inputEither =
inputConverter.stringToUnsignedInteger(event.numberString);
inputEither.fold((failure) => emit(Error(message: invalidInputMessage)),
(integer) async {
emit(Loading());
final failureOrTrivia =
await getConcreteNumberTrivia(Params(number: integer));
emit(
failureOrTrivia.fold(
(failure) => Error(message: _mapFailureToMessage(failure)),
(trivia) => Loaded(trivia: trivia),
),
);
});
});
}
I was getting error which says I had not awaited some Future - https://pastebin.com/FWTFKYVH but it didn't seems to be true, cause I have only one function getConcreteNumberTrivia
which returns Future and it is awaited.
But when I'm cut off last emit to separate function like this:
void _eitherLoadedOrErrorState(
Either<Failure, NumberTrivia> failureOrTrivia,
) {
emit(
failureOrTrivia.fold(
(failure) => Error(message: _mapFailureToMessage(failure)),
(trivia) => Loaded(trivia: trivia),
),
);
}
Code starts working properly. I don't get it, I'd just moved code to void function, which do not doing anything additional, can somebody explain me why?
Lets remove some of the overhead and look at the details:
inputEither.fold((failure) { /*...*/ }, (integer) async { /*...*/ });
Looking at the fold method, it returns B
, where B
is the common return value of it's two functions. Your first function returns void
, your second function returns Future<void>
since you marked it async
. So the common return value of those two functions is probably FutureOr<void>
. And that should be await
ed.
await inputEither.fold((failure) { /*...*/ }, (integer) async { /*...*/ });
Now those were the technical details. Some personal observation: functional programming is meant to make the code easier to structure and easier to read. To me, yours is harder to read than it's OOP equivalent. I don't think that's a good thing. Having multiple layers of folds makes it hard to read (for me, who is not used to it). It might become a lot easier to read and a lot easier to handle and understand for you, if you did not use lambda functions, but instead wrote real functions with real return types and parameters. Then you will see for yourself what I just explained above.