Flutter Bloc Error : emit was called after an event handler completed normally - between two functions
void _onChangeLanguage(
ChangeLanguageEvent event,
Emitter<StateA> emit, {
bool isFromLogin = false,
}) async
This should be a major red flag. A call marked as async
, but not returning a Future<>
. There is no way, the caller could possibly await this call. Or even know that they should await this call.
Make it return a proper Future<void>
instead of just void
and your bloc should pick up on that and properly await the call.
There even is a linter rule for this: avoid_void_async. Did you turn off your linter? Don't do that. Turn your linter on and listen to it. Your other function has the same problem.
Daniel Roldán
Joven amante del desarrollo movil que busca sobrellevar su experiencia en grande
Updated on December 01, 2022Comments
-
Daniel Roldán over 1 year
I have the following problem...
emit was called after an event handler completed normally. This is usually due to an unawaited future in an event handler. Please make sure to await all asynchronous operations with event handlers and use emit.isDone after asynchronous operations before calling emit() to ensure the event handler has not completed.
BAD on((event, emit) { future.whenComplete(() => emit(...)); });
GOOD on((event, emit) async { await future.whenComplete(() => emit(...)); }); )
What happens is that in a function called _onLogIn, if the user has changed the language, it goes from there to another function inside the bloc, these two functions do not depend on each other, I mean that each function is called in different pages of the application, but still _onLogIn checks the _onChangeLanguage function.
UserBloc({this.usecases}) : super(UserInitial()) { on<LogInEvent>(_onLogIn); on<ChangeLanguageEvent>(_onChangeLanguage); }
_onLogIn function :
void _onLogIn( LogInEvent event, Emitter<StateA> emit, ) async { emit(UserLoading()); final userOrFailure = await services.logIn( x: event.x, y: event.y, ); await userOrFailure.fold((user) async { /// If the user is logging in for the first time and does not /// have a preferred language. if (user.preferredLanguage == null) { emit(UserSuccess()); emit(UserAlreadyLogged(connectedUser)); } else { /// An ChangeLanguageEvent object ChangeLanguageEvent event = ChangeLanguageEvent( user.preferredLanguage, user.someId, ); /// Call the other function in the same bloc this._onChangeLanguage( event, emit, isFromLogin: true, ); } }, (failure) { emit(UserError(failure.message)); }); }
_onChangeLanguage function :
void _onChangeLanguage( ChangeLanguageEvent event, Emitter<StateA> emit, { bool isFromLogin = false, }) async { final successOrFailure = await services.updateLanguage( event.language, event.someId, ); await successOrFailure.fold( // ! HERE THE ERROR WHEN I LOG IN; but when i changed the language from the application i don't have an error (language) async { emit(ChangeAppLanguage(language)); final sessionOrFailure = await services.getSession(); sessionOrFailure.fold( (session) { /// I need this condition to know if the language comes from login if (isFromLogin) { emit(UserSuccess()); } emit(UserAlreadyLogged(session)); }, (failure) => emit(UserError(failure.message)), ); }, (failure) { emit(UserError(failure.message)); }, ); }
Any idea why? Thank you
-
pskink about 2 yearsi assume that
_onLogIn
is called inside someon<...>
method, right? if so it seems that youremit
is called afteron
method finished - most likely this is because yourfold
methods are not awaiting theirasync
callbacks -
Daniel Roldán about 2 years@pskink Yeah yeah, both, i add it in the description And have you an idea how can i fixed it ?
-
-
Daniel Roldán about 2 yearsThat helps me a lot, thanks! Put "await" before calling the other function too.