skip to Main Content
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:moms/features/chat/domain/entities/message_entity.dart';
import 'package:moms/features/chat/domain/usecases/send_message.dart';
import 'package:moms/features/chat/domain/usecases/get_messages.dart';
import 'package:moms/features/chat/domain/usecases/get_or_create_thread_usecase.dart';

part 'chat_event.dart';
part 'chat_state.dart';

class ChatBloc extends Bloc<ChatEvent, ChatState> {
  final GetOrCreateThread getOrCreateThread;
  final GetMessages getMessages;
  final SendMessage sendMessage;

  ChatBloc({
    required this.getOrCreateThread,
    required this.getMessages,
    required this.sendMessage,
  }) : super(ChatInitial()) {
    on<LoadChatThreadEvent>(_onLoadChatThreadEvent);
    on<LoadMessagesEvent>(_onLoadMessagesEvent);
    on<SendMessageEvent>(_onSendMessageEvent);
  }

  Future<void> _onLoadChatThreadEvent(
      LoadChatThreadEvent event, Emitter<ChatState> emit) async {
    emit(ChatLoading());

    final threadResult = await getOrCreateThread(event.gigId, event.bidId);
    threadResult.fold(
      (failure) =>
          emit(ChatError('Failed to load chat thread: ${failure.message}')),
      (threadId) async {
        await _loadMessagesForThread(threadId, emit);
      },
    );
  }

  Future<void> _onLoadMessagesEvent(
      LoadMessagesEvent event, Emitter<ChatState> emit) async {
    emit(ChatLoading());
    await _loadMessagesForThread(event.threadId, emit);
  }

  Future<void> _onSendMessageEvent(
      SendMessageEvent event, Emitter<ChatState> emit) async {
    emit(ChatLoading());

    final sendResult =
        await sendMessage(event.threadId, event.content, event.senderId);
    sendResult.fold(
      (failure) =>
          emit(ChatError('Failed to send message: ${failure.message}')),
      (message) async {
        await _loadMessagesForThread(event.threadId, emit);
      },
    );
  }

  Future<void> _loadMessagesForThread(
      int threadId, Emitter<ChatState> emit) async {
    final messagesResult = await getMessages(threadId);
    messagesResult.fold(
      (failure) =>
          emit(ChatError('Failed to load messages: ${failure.message}')),
      (messages) => emit(ChatLoaded(threadId: threadId, messages: messages)),
    );
  }
}

For the above chat_bloc code, I am getting the error:

E/flutter (18794): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'package:bloc/src/emitter.dart': Failed assertion: line 114 pos 7: '!_isCompleted': 
E/flutter (18794): emit was called after an event handler completed normally.
E/flutter (18794): This is usually due to an unawaited future in an event handler.
E/flutter (18794): Please make sure to await all asynchronous operations with event handlers
E/flutter (18794): and use emit.isDone after asynchronous operations before calling emit() to
E/flutter (18794): ensure the event handler has not completed.
E/flutter (18794): 
E/flutter (18794):   **BAD**
E/flutter (18794):   on<Event>((event, emit) {
E/flutter (18794):     future.whenComplete(() => emit(...));
E/flutter (18794):   });
E/flutter (18794): 
E/flutter (18794):   **GOOD**
E/flutter (18794):   on<Event>((event, emit) async {
E/flutter (18794):     await future.whenComplete(() => emit(...));
E/flutter (18794):   });
E/flutter (18794): 
E/flutter (18794): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:50:61)
E/flutter (18794): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
E/flutter (18794): #2      _Emitter.call (package:bloc/src/emitter.dart:114:7)
E/flutter (18794): #3      ChatBloc._loadMessagesForThread.<anonymous closure> (package:project/features/chat/presentation/bloc/chat_bloc.dart:66:25)
E/flutter (18794): #4      Right.fold (package:dartz/src/either.dart:200:64)
E/flutter (18794): #5      ChatBloc._loadMessagesForThread (package:project/features/chat/presentation/bloc/chat_bloc.dart:63:20)
E/flutter (18794): <asynchronous suspension>
E/flutter (18794): #6      ChatBloc._onLoadChatThreadEvent.<anonymous closure> (package:project/features/chat/presentation/bloc/chat_bloc.dart:34:9)
E/flutter (18794): <asynchronous suspension>

I tried multiple ways to solve it, but the error is redundant.

I am trying to implement the chat functionality. the backend works fine but the bloc is giving this error repetively in the emit. Also, I am not using web sockets here.

I am new to bloc and hence finding it difficult to solve this error.

2

Answers


  1. Try this changes in bloc:

     Future<void> _onSendMessageEvent(
        SendMessageEvent event, 
        Emitter<ChatState> emit,
     ) async {
          ... ...
          (message) async {
            // await _loadMessagesForThread(event.threadId, emit); <- remove
            add(LoadMessagesEvent(event.threadId));
          },
        );
      }
    ...
      Future<void> _onSendMessageEvent(
          SendMessageEvent event, 
          Emitter<ChatState> emit,
      ) async {
        ... ...
          (message) async {
            //await _loadMessagesForThread(event.threadId, emit); <-- remove
            add(LoadMessagesEvent(event.threadId));
          },
        );
      }
    
    Login or Signup to reply.
  2. You have to add await before .fold like this for async method

    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:moms/features/chat/domain/entities/message_entity.dart';
    import 'package:moms/features/chat/domain/usecases/send_message.dart';
    import 'package:moms/features/chat/domain/usecases/get_messages.dart';
    import 'package:moms/features/chat/domain/usecases/get_or_create_thread_usecase.dart';
    
    part 'chat_event.dart';
    part 'chat_state.dart';
    
    class ChatBloc extends Bloc<ChatEvent, ChatState> {
      final GetOrCreateThread getOrCreateThread;
      final GetMessages getMessages;
      final SendMessage sendMessage;
    
      ChatBloc({
        required this.getOrCreateThread,
        required this.getMessages,
        required this.sendMessage,
      }) : super(ChatInitial()) {
        on<LoadChatThreadEvent>(_onLoadChatThreadEvent);
        on<LoadMessagesEvent>(_onLoadMessagesEvent);
        on<SendMessageEvent>(_onSendMessageEvent);
      }
    
      Future<void> _onLoadChatThreadEvent(
          LoadChatThreadEvent event, Emitter<ChatState> emit) async {
        emit(ChatLoading());
    
        final threadResult = await getOrCreateThread(event.gigId, event.bidId);
        await threadResult.fold( // new here
          (failure) =>
              emit(ChatError('Failed to load chat thread: ${failure.message}')),
          (threadId) async {
            await _loadMessagesForThread(threadId, emit);
          },
        );
      }
    
      Future<void> _onLoadMessagesEvent(
          LoadMessagesEvent event, Emitter<ChatState> emit) async {
        emit(ChatLoading());
        await _loadMessagesForThread(event.threadId, emit);
      }
    
      Future<void> _onSendMessageEvent(
          SendMessageEvent event, Emitter<ChatState> emit) async {
        emit(ChatLoading());
    
        final sendResult =
            await sendMessage(event.threadId, event.content, event.senderId);
        await sendResult.fold( // new here
          (failure) =>
              emit(ChatError('Failed to send message: ${failure.message}')),
          (message) async {
            await _loadMessagesForThread(event.threadId, emit);
          },
        );
      }
    
      Future<void> _loadMessagesForThread(
          int threadId, Emitter<ChatState> emit) async {
        final messagesResult = await getMessages(threadId);
        messagesResult.fold(
          (failure) =>
              emit(ChatError('Failed to load messages: ${failure.message}')),
          (messages) => emit(ChatLoaded(threadId: threadId, messages: messages)),
        );
      }
    }```
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search