Search code examples
node.jsangularexpresssocket.iochat

socket.io feature doesn't work for user to group communication but works for user to user communication


I am creating social medial like app with Angular on front end and Node.js on back end. I successfully implemented user to user communication with typing indicator and message receiving functionality. Now I am trying to create user to group communication but it seems like the socket.io just doesn't emit anything to the front. I debugged my backend and all the data is received correctly but nothing is emitted to the front. I am currently in development mode so there are no proxy issues here. The idea is to set users with their group id and then emit the event to each user for that gorup.

Here is Angular part:

This is in constructor -> this.socket = io('http://localhost:3000'); Here is the event emitter and event handlers in ngOnInit

// Connection
const user_id = this.mineId;
const group_id = this.chat.group_id as number;
this.socket.emit('groupUserConnected', { user_id, group_id });

// Socket event listeners
});
this.socket.on('gTyping',({ user_id, username }: { user_id: number; username: string }) => {
            if (user_id !== this.mineId) {
              this.userThatIsTyping = username;
              this.isTyping = true;

              if (this.typingTimerSubscription) {
                this.typingTimerSubscription.unsubscribe();
              }
              this.typingTimerSubscription = timer(1500).subscribe(() => {
                this.isTyping = false;
              });
            }
          }
);

And here is the typing Emitter: this.socket.emit('groupTyping', { myId, group_id, myUsername });

Here is the Node.js part:

const groupConnectedClients = new Map();

socket.on("groupUserConnected", ({ user_id, group_id }) => {
    if (!groupConnectedClients.has(group_id)) {
      groupConnectedClients.set(group_id, new Set());
    }
    groupConnectedClients.get(group_id).add(user_id);
  });

socket.on("groupTyping", ({ myId, group_id, myUsername }) => {
    const users = groupConnectedClients.get(group_id);
    for (const user of users) {
      io.to(user).emit("gTyping", {
        myId,
        myUsername,
      });
    }
  });

Solution

  • I don't quite understand why you are using groupConnectedClients

    There are rooms in socketio that you can connect your users to, it's much more convenient

    Use socket.join(group_id) to join a room

    You don't need a loop to send events, there are just a few commands:

    // to all clients in room except the sender
    socket.to(group_id).emit(/* ... */);
    
    // to all clients in room
    io.in(group_id).emit(/* ... */);
    

    Room docs: https://socket.io/docs/v4/rooms/ Emit cheatsheet: https://socket.io/docs/v4/emit-cheatsheet/