Flutter Bloc Error : emit was called after an event handler completed normally - between two functions

Flutter Bloc Error : emit was called after an event handler completed normally - between two functions

我有以下问题...

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(...)); }); )

发生的事情是,在一个名为 _onLogIn 的函数中,如果用户更改了语言,它会从那里转到 bloc 内的另一个函数,这两个函数不依赖彼此,我的意思是每个函数在应用程序的不同页面中被调用,但仍然 _onLogIn 检查 _onChangeLanguage 函数。

  UserBloc({this.usecases}) : super(UserInitial()) {
    on<LogInEvent>(_onLogIn);
    on<ChangeLanguageEvent>(_onChangeLanguage);
  }

_onLogIn 函数:

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 函数:

  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));
      },
    );
  }

知道为什么吗?谢谢

void _onChangeLanguage(
    ChangeLanguageEvent event,
    Emitter<StateA> emit, {
    bool isFromLogin = false,
  }) async

这应该是一个重大危险信号。标记为 async 的呼叫,但未 return 呼叫 Future<>。没办法,调用者可能会等待这个调用。或者甚至知道他们应该等待这个电话。

让它 return 成为一个合适的 Future<void> 而不是 void,你的集团应该接受并适当地等待电话。

甚至有一个 linter 规则:avoid_void_async。你关掉 linter 了吗?不要那样做。打开你的 linter 并听它。你的其他功能也有同样的问题。