flutter_bloc (эмиссия была вызвана после обычного завершения обработчика событий

#flutter #flutter-bloc

#трепетать #флаттер-блок

Вопрос:

Итак, я работал с Django rest framework, создавая свои API и все такое. И я хотел проверить, смогу ли я получить ответ от бэкенда. Итак, я смог получить ответ. Но я видел некоторые проблемы на консоли отладки. Пожалуйста, помогите мне разобраться в проблеме. Это то, что я получил на консоли отладки.

 Restarted application in 1,314ms. I/flutter ( 1751): {"token":"0d15f2d45f11869174395d623c066080bd2ade52"} E/flutter ( 1751): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: 'package:bloc/src/bloc.dart': Failed assertion: line 232 pos 7: '!_isCompleted': E/flutter ( 1751): E/flutter ( 1751): E/flutter ( 1751): emit was called after an event handler completed normally. E/flutter ( 1751): This is usually due to an unawaited future in an event handler. E/flutter ( 1751): Please make sure to await all asynchronous operations with event handlers E/flutter ( 1751): and use emit.isDone after asynchronous operations before calling emit() to E/flutter ( 1751): ensure the event handler has not completed. E/flutter ( 1751): E/flutter ( 1751): **BAD** E/flutter ( 1751): onlt;Eventgt;((event, emit) { E/flutter ( 1751): future.whenComplete(() =gt; emit(...)); E/flutter ( 1751): }); E/flutter ( 1751): E/flutter ( 1751): **GOOD** E/flutter ( 1751): onlt;Eventgt;((event, emit) async { E/flutter ( 1751): await future.whenComplete(() =gt; emit(...)); E/flutter ( 1751): }); E/flutter ( 1751): E/flutter ( 1751): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39) E/flutter ( 1751): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5) E/flutter ( 1751): #2 _Emitter.call E/flutter ( 1751): #3 new LoginFormBloc.lt;anonymous closuregt;.lt;anonymous closuregt; E/flutter ( 1751): lt;asynchronous suspensiongt; E/flutter ( 1751): Reloaded 1 of 746 libraries in 1,055ms.  

Вот мой исходный код:

login_form_event.dart

 part of 'login_form_bloc.dart';  @freezed class LoginFormEvent with _$LoginFormEvent {  const factory LoginFormEvent.emailChanged(String emailStr) = _EmailChanged;  const factory LoginFormEvent.passwordChanged(String passwordStr) =  _PasswordChanged;  const factory LoginFormEvent.loggedIn() = _LoggedIn; }  

login_form_state.dart

 part of 'login_form_bloc.dart';  @freezed class LoginFormState with _$LoginFormState {  const factory LoginFormState({  required EmailAddress emailAddress,  required Password password,  required bool isSubmitting,  required bool showErrorMessages,  required Optionlt;Eitherlt;AuthFailure, TokenValuegt;gt; authFailureOrSuccessOption,  }) = _LoginFormState;   factory LoginFormState.initial() =gt; LoginFormState(  emailAddress: EmailAddress(''),  password: Password(''),  isSubmitting: false,  showErrorMessages: false,  authFailureOrSuccessOption: none(),  ); }  

login_form_bloc.dart

 class LoginFormBloc extends Bloclt;LoginFormEvent, LoginFormStategt; {  LoginFormBloc(this._getAuthInfo) : super(LoginFormState.initial()) {  onlt;LoginFormEventgt;(  (event, emit) {  event.map(  emailChanged: (e) {  emit(  state.copyWith(  emailAddress: EmailAddress(e.emailStr),  authFailureOrSuccessOption: none(),  ),  );  },  passwordChanged: (e) {  emit(  state.copyWith(  password: Password(e.passwordStr),  authFailureOrSuccessOption: none(),  ),  );  },  loggedIn: (e) async {  final isEmailValid = state.emailAddress.value.isRight();  final isPasswordValid = state.password.value.isRight();   Eitherlt;AuthFailure, TokenValuegt;? loginFailureOrSuccess;   if (isEmailValid amp;amp; isPasswordValid) {  emit(  state.copyWith(  isSubmitting: true,  authFailureOrSuccessOption: none(),  ),  );  loginFailureOrSuccess = await _getAuthInfo(  Params(  emailAddress: state.emailAddress,  password: state.password,  ),  );  }   //The error is pointed to this emit below  emit(  state.copyWith(  isSubmitting: false,  showErrorMessages: true,  authFailureOrSuccessOption: optionOf(loginFailureOrSuccess),  ),  );  },  );  },  );  }  final GetAuthToken _getAuthInfo; }  

Ошибка указана на 2-м выделении внутри обработчика событий LoggedIn.

Комментарии:

1. Что случилось с методом карты? Почему бы не использовать обычную onlt;Eventgt; нотацию, это, вероятно, исправит проблему… Если вы не хотите использовать обычный on метод, не могли бы вы показать реализацию этого map метода?

2. Метод карты существует, потому что я использовал объединения, предлагаемые замороженным пакетом.

3. @h8moss смотрите обновленный пост. Может быть, это поможет.

4. Сейчас этот вопрос решен.

5. Я вижу, рад слышать, что проблема устранена

Ответ №1:

Все, что мне нужно было сделать, это добавить await ключевое слово перед вызовом event.map и пометить функцию, async как показано ниже. Кроме того, я прямо упомянул, что должны возвращать мои отдельные обработчики событий. В данном случае так оно и было FutureOrlt;voidgt; .

 class LoginFormBloc extends Bloclt;LoginFormEvent, LoginFormStategt; {  LoginFormBloc(this._getAuthInfo) : super(LoginFormState.initial()) {  onlt;LoginFormEventgt;(  (event, emit) async {  await event.maplt;FutureOrlt;voidgt;gt;(  emailChanged: (e) {  emit(  state.copyWith(  emailAddress: EmailAddress(e.emailStr),  authFailureOrSuccessOption: none(),  ),  );  },  passwordChanged: (e) {  emit(  state.copyWith(  password: Password(e.passwordStr),  authFailureOrSuccessOption: none(),  ),  );  },  loggedIn: (e) async {  final isEmailValid = state.emailAddress.value.isRight();  final isPasswordValid = state.password.value.isRight();   Eitherlt;AuthFailure, TokenValuegt;? loginFailureOrSuccess;   if (isEmailValid amp;amp; isPasswordValid) {  emit(  state.copyWith(  isSubmitting: true,  authFailureOrSuccessOption: none(),  ),  );  loginFailureOrSuccess = await _getAuthInfo(  Params(  emailAddress: state.emailAddress,  password: state.password,  ),  );  }  emit(  state.copyWith(  isSubmitting: false,  showErrorMessages: true,  authFailureOrSuccessOption: optionOf(loginFailureOrSuccess),  ),  );  },  );  },  );  }  final GetAuthToken _getAuthInfo; }