为什么将 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>
。那应该 await
ed.
await inputEither.fold((failure) { /*...*/ }, (integer) async { /*...*/ });
现在这些是技术细节。一些个人观察:函数式编程旨在使代码更易于结构化和更易于阅读。对我来说,你的比它的 OOP 等价物更难阅读。我不认为这是一件好事。有多层褶皱,读起来很费劲(对我来说,不习惯的人)。如果您不使用 lambda 函数,而是编写具有真实 return 类型和参数的真实函数,它可能会变得更容易阅读,更容易处理和理解。然后你会亲眼看到我刚才解释的内容。
nvoigt 解释了您出错的原因。你提取方法后没有报错的原因是你没有提取emit
参数。您提取的方法中的 emit
指的是 Bloc
class 的 emit 方法,该方法“仅供内部使用,切勿在测试之外直接调用”到文档。
我遇到了一个奇怪的问题,我花了几个小时解决。我有一个 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>
。那应该 await
ed.
await inputEither.fold((failure) { /*...*/ }, (integer) async { /*...*/ });
现在这些是技术细节。一些个人观察:函数式编程旨在使代码更易于结构化和更易于阅读。对我来说,你的比它的 OOP 等价物更难阅读。我不认为这是一件好事。有多层褶皱,读起来很费劲(对我来说,不习惯的人)。如果您不使用 lambda 函数,而是编写具有真实 return 类型和参数的真实函数,它可能会变得更容易阅读,更容易处理和理解。然后你会亲眼看到我刚才解释的内容。
nvoigt 解释了您出错的原因。你提取方法后没有报错的原因是你没有提取emit
参数。您提取的方法中的 emit
指的是 Bloc
class 的 emit 方法,该方法“仅供内部使用,切勿在测试之外直接调用”到文档。