I'm in a bit of a pickle. Not sure what I'm doing wrong here.
我现在有点为难。不知道我到底做错了什么。
The abstract logic is like this:
抽象的逻辑是这样的:
- Show users are online only when they are part of a chat. A user can be part of many chats and multiple users can be part of one chat.
- When I initially connect, I send all of the chats that the user is part of.
Here is the issue. I have one user create a chat and add the second user to it. When I refresh either of the pages of the users, only one of them gets added to the room.
If I refresh the first users page, then the second user gets added to the room, and vice versa.
以下是问题所在。我让一个用户创建聊天,并将第二个用户添加到其中。当我刷新用户的任一页面时,只有一个页面被添加到聊天室。如果我刷新第一个用户页面,则第二个用户将被添加到聊天室,反之亦然。
At no point do both of them get added to the same room.
在任何情况下,他们都不会被添加到同一个房间。
Here are screenshots of my implementation.
以下是我实现的屏幕截图。
Server:
服务器:
const sockets = new Map<string, number>();
io.on('connection', (socket) => {
// console.log({sockets: io.sockets.adapter.sids});
socket.on('newUserJoined', async (data: { chatIds: number[], user: number }) => {
if(!data.chatIds || !data.user ) return;
sockets.set(socket.id, data.user);
socket.join(data.chatIds.map(t => `room${t}`));
// console.log('connect', {user: data.user, date: new Date()})
// console.log({ rooms: data.chatIds.map(t => `room${t}`) });
console.log('Connecting socket', { id: socket.id, user: data.user, chatIds: data.chatIds });
io.to(data.chatIds.map(t => `room${t}`)).emit('onlineUsers', [data.user]);
});
socket.on('disconnect', () => {
let rooms = Array.from(io.sockets.adapter.sids.get(socket.id) ?? []);
for(var room in rooms) {
socket.leave(room);
}
console.log('Disconnecting socket', socket.id);
sockets.delete(socket.id);
// console.log({onlineUsers: Array.from(sockets.values())});
io.to(rooms).emit('onlineUsers', Array.from(sockets.values()));
// console.log('disconnect', {onlineUsers, date: new Date()})
});
socket.on('sendMessage', (message: { text: string, chatId: number, senderId: number }) => {
io.to(`room${message.chatId}`).emit('getMessage', message);
});
});
Server explanation:
服务器说明:
- I'm keeping a Map of all connected sockets. It's a structure of <socket_id, user_id>.
- When I disconnect from a socket, I go through all of the rooms that the socket was part of. Then I delete the socket from the Map. And at the end emit "onlineUsers" so other users can see that someone disconnected.
Client:
客户端:
useEffect(() => {
if(!socket || !user?.id || !chatResponse || chatResponse.data.length == 0) return;
console.log({chatResponse});
socket.emit("newUserJoined", { chatIds: chatResponse?.data.map((c: ChatFull) => c.id), user: user.id });
socket?.on('onlineUsers', (ids: number[]) => {
console.log('Online users', {ids});
setOnlineUsers([...onlineUsers, ...ids]);
});
return () => {
socket.off('onlineUsers');
}
}, [chatResponse]);
Client explanation:
客户端说明:
- "chatResponse" is the response from the backend that gives all the chats in which the logged in user is part of.
- When all the chats are loaded I emit it as "newUserJoined" so that the other users of that chat can see who is online.
- "onlineUsers" receiving emit just receives a list of users that are already online.
Any help on this? Maybe my approach is wrong to the problem. I can't really find a guide when there are multiple chats, that can exist during connection, and multiple users in any given chat.
对此有什么帮助吗?也许我的方法在这个问题上是错误的。我真的找不到指南,当有多个聊天,可能存在于连接期间,并且在任何给定的聊天中有多个用户。
更多回答
优秀答案推荐
In the newUserJoined
event handler, you are only sending the just logged-in user. You should send all of them. Change this line
在newUserJoven事件处理程序中,您只发送刚刚登录的用户。你应该把它们都寄出去。更改此行
io.to(data.chatIds.map(t =› 'room${t')).emit('onlineUsers', [data.user]);
to
至
io.to(data.chatIds.map(t =› 'room${t')).emit('onlineUsers', Array.from(sockets.values()));
更多回答
Oh wow, great job on this. I was thinking by doing it like this, then users that aren't part of the chat would be getting online users, but nope that's it. In hindsight, I believe the issue was I was console logging the list of users at the start of the connection. I should have logged after each user joined. I'll mark this as the answer. Thank you!
哦,哇,干得好。我在想,如果这样做,那么没有参与聊天的用户就会获得在线用户,但事实并非如此。事后看来,我认为问题在于我在连接开始时通过控制台记录用户列表。我应该在每个用户加入后才登录。我会把这个标记为答案。谢谢!
我是一名优秀的程序员,十分优秀!