简体   繁体   中英

Why separating emit() to void function made Bloc working?

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.

nvoigt explained why you got an error. The reason you didn't get an error after extracting the method is that you didn't extract the emit parameter. The emit in your extracted method refers to the Bloc class's emit method, which "is only for internal use and should never be called directly outside of tests" according to the documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM