为什么将 emit() 与 void 函数分开会使 Bloc 工作?

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

我遇到了一个奇怪的问题,我花了几个小时解决。我有一个 bloc 文件,我在其中使用 dartZ 来更轻松地维护错误。当我像这样使用 bloc 时:

  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),
          ),
        );
      });
    });
  }

我收到错误消息说我没有等待某个 Future - https://pastebin.com/FWTFKYVH 但它似乎不是真的,因为我只有一个函数 getConcreteNumberTrivia returns未来,敬请期待。

但是当我被切断时,最后发射到像这样的分离函数:

  void _eitherLoadedOrErrorState(
    Either<Failure, NumberTrivia> failureOrTrivia,
  ) {
    emit(
      failureOrTrivia.fold(
        (failure) => Error(message: _mapFailureToMessage(failure)),
        (trivia) => Loaded(trivia: trivia),
      ),
    );
  }

代码开始正常工作。 我不明白,我只是将代码移动到 void 函数,它没有做任何额外的事情,有人能解释一下为什么吗?

让我们删除一些开销并查看详细信息:

inputEither.fold((failure) { /*...*/ }, (integer) async { /*...*/ });

查看 fold 方法,它 returns B,其中 B 是它的两个函数的公共 return 值。你的第一个函数 returns void,你的第二个函数 returns Future<void> 因为你标记了它 async。所以这两个函数的共同 return 值可能是 FutureOr<void>。那应该 awaited.

await inputEither.fold((failure) { /*...*/ }, (integer) async { /*...*/  });

现在这些是技术细节。一些个人观察:函数式编程旨在使代码更易于结构化和更易于阅读。对我来说,你的比它的 OOP 等价物更难阅读。我不认为这是一件好事。有多层褶皱,读起来很费劲(对我来说,不习惯的人)。如果您不使用 lambda 函数,而是编写具有真实 return 类型和参数的真实函数,它可能会变得更容易阅读,更容易处理和理解。然后你会亲眼看到我刚才解释的内容。

nvoigt 解释了您出错的原因。你提取方法后没有报错的原因是你没有提取emit参数。您提取的方法中的 emit 指的是 Bloc class 的 emit 方法,该方法“仅供内部使用,切勿在测试之外直接调用”到文档。