Reputation: 33
i have a bloc class which has number of methods that should execute sequentially. These methods are async methods and after all is fully executed i need to call and emit for the success state. The overall application logic is for a login screen. after the login button clicked SubmitLogin is called in LoginBloc class. i'll paste the code snippet for reference.
LoginBloc class
class LoginBloc extends Bloc<LoginEvent, LoginState> {
final UserRepository userRepository;
LoginBloc({required this.userRepository}) : super(LoginInitial()) {
on<SubmitLogin>(_onSubmitLogin);
}
Future<void> _onSubmitLogin(
SubmitLogin event,
Emitter<LoginState> emit,
) async {
emit(LoginLoading());
if (event.email.isNull || event.password.isNull) {
emit(LoginFailure(status: AuthStatus.INVALID_CREDENTIALS));
return;
}
try {
final Either<AuthStatus, bool> authResult =
await userRepository.authenticateUser(
event.email,
event.password,
);
authResult.fold(
(AuthStatus failure) {
emit(LoginFailure(status: failure));
},
(bool status) async {
await method1(event, emit).whenComplete(() {
emit(LoginSuccess());
/// this is where the error shows up ///
});
},
);
if (emit.isDone) {
emit(LoginSuccess());
}
} catch (error) {
emit(LoginFailure(error));
}
}
Future<void> method1(
SubmitLogin event,
Emitter<LoginState> emit,
) async {
try {
final Either<ApiFailure, Para1> configResult =
await userRepository.fetchConfigurations();
return configResult.fold(
(ApiFailure apiFailure) {
emit(LoginFailure(status: AuthStatus.SERVER_ERROR));
},
(Para1 para1) async {
await method2(
event,
emit,
para1,
);
},
);
} catch (error) {
emit(LoginFailure(error));
}
}
Future<void> method2(
SubmitLogin event,
Emitter<LoginState> emit,
Para1 para1,
) async {
try {
final Either<ApiFailure, Para2> accessResult =
await userRepository.accessConfigurations();
return accessResult.fold(
(ApiFailure apiFailure) {
emit(LoginFailure(error));
},
(Para2 para2) async {
await method3(
event,
emit,
para1,
para2,
);
},
);
} catch (error) {
emit(LoginFailure(error));
}
}
Future<void> method3(
SubmitLogin event,
Emitter<LoginState> emit,
Para1 para1,
Para2 para2,
) async {
try {
await userRepository.saveUserData(
Para1,
Para2,
event.email,
event.password,
);
} catch (error) {
emit(LoginFailure(error));
}
}
}
The particular error im getting is this !_isCompleted "\n\n\nemit was called after an event handler completed normally.\nThis is usually due to an unawaited future in an event handler.\nPlease make sure to await all asynchronous operations with event handlers\nand use emit.isDone after asynchronous operations before calling emit() to\nensure the event handler has not completed.\n\n BAD\n on((event, emit) {\n future.whenComplete(() => emit(...));\n });\n\n GOOD\n on((event, emit) async {\n await future.whenComplete(() => emit(...));\n });\n"
How can i rectify this ? I appreciate any help in solving this issue. this is the only place im stuck with.
I tried number of ways to make these methods execute sequentially and call an emi success after all is done. but all the time i get the above mentioned error.
Upvotes: 1
Views: 1041
Reputation: 33
Can modify this line
LoginBloc({required this.userRepository}) : super(LoginInitial()) {
on<SubmitLogin>((event, emit) async {
await _onSubmitLogin(event, emit).whenComplete(() {
// emit.isDone;
emit(LoginSuccess());
});
});
}
then everything will execute without an issue
Upvotes: 0