I am using bloc and socket.io in my flutter application to react to login states from the server.
Future<void> _setLoginListener(SetLoginListener event, Emitter<LoginState> emit)async{
final socketClient = SocketClient.instance.socket;
try {
socketClient?.on('loginRequestHandler',(data){
if (data == null) {
emit(LoginError("Email or Password wrong!"));
} else {
emit(LoginSuccessfully("Login granted"));
CurrentUser currentUser = CurrentUser.fromJson(data);
}
});
} catch(e) {
emit(LoginError(e.toString()));
}
I understand the exception, that emit()
is called, but the future is not "done" yet, but I don't understand how to handle a future in this case.
There is no way to use an await socketClient?.on()...
or an await emit()
.
I found some post on Stackoverflow to solve the error, but they are about different code situations.
I am thankful for every help!
As @pskink pointed out in the comment, when an event is completely handled, no emits are allowed, so if you want to still emit a new state you will have to create another event that emits the state that you want and trigger it where you currently emitting the new state, then the issue will go away!
void _setLoginListener(SetLoginListener event, Emitter<LoginState> emit) {
final socketClient = SocketClient.instance.socket;
try {
socketClient?.on('loginRequestHandler', (data) {
if (data == null) {
// Removed the emit and used the add instead
add(LoginFailed());
} else {
// Removed the emit and used the add instead
add(LoginSucceeded(data: data)); // Don't forget to pass the data to the new event
}
});
} catch (e) {
// Might need to be moved to another event, maybe call it SocketFailure
emit(LoginError(e.toString()));
}
}
void _onLoginFailed(LoginFailed event, Emitter<LoginState> emit) {
emit(LoginError("Email or Password wrong!"));
}
void _onLoginSucceeded(LoginSucceeded event, Emitter<LoginState> emit) {
emit(LoginSuccessfully("Login granted"));
CurrentUser currentUser = CurrentUser.fromJson(event.data); // Here you can use the data passed to the event
}
And the events would look something like
class LoginFailed extends ... {
const LoginFailed();
}
class LoginSucceeded extends ... {
final data;
const LoginSucceeded({required this.data});
}