Socket.io双重事件,已解决连接但未断开连接的问题



我是socket.io和next的新手。JS。在将socket.io集成到Next中后,我注意到连接代码启动了两次,使我的连接数增加了一倍(我需要准确(。

我在谷歌上搜索了很多,但没有找到有效的解决方案,包括socket.one('connect'(。我通过创建手动连接事件并在启动时从客户端发出来解决这个问题。我现在可以看到一个准确的连接计数,只要没有人断开连接。

至于断开连接,我看到了同样的问题,每个用户都会触发两次断开连接事件,但我不知道如何在断开连接时在客户端上手动发出。

关于如何发出与客户端的手动断开连接,有什么建议吗?

还是一种新的方法?也许可以使用一个集合来保存客户端ID,而不是增加一个int?重复的收集计数可能会对性能不利(每个用户都会经常访问总计数,可能是每秒一次(。

服务器代码

const SERVER_STATE = {
totalConnections: 0
} 
// socket.io server
io.on('connection', socket => {
socket.once('userConnectOnce', () => {
SERVER_STATE.totalConnections++;
socket.emit('message', `Welcome from server. There are a total of ${SERVER_STATE.totalConnections} connections.`);
socket.broadcast.emit('message', `New user joined. There are a total of ${SERVER_STATE.totalConnections} connections.`);
});
socket.once('disconnect', () => {       // this fires more than once
SERVER_STATE.totalConnections--;
socket.broadcast.emit('message', `Other user disonnected. There are now ${SERVER_STATE.totalConnections} connections.`);
});
});

客户端代码

const Index = () => {
const socket = useSocket('message', (data) => {
console.log(data);
});
socket.emit('userConnectOnce', 'client-initiated userConnectOnce');
return (
<></>
);
};

注意:useSocket((是下一个示例repo中的自定义钩子,用于将socket.on((包装在useEffect((中并返回套接字。我找不到链接,也不确定它是否相关,但这里有一些代码:

import { useEffect } from 'react';
import io from 'socket.io-client';
const socket = io();
export default function useSocket(eventName, cb) {
useEffect(() => {
socket.on(eventName, cb);
return function socketCleanup() {
socket.off(eventName, cb);
}
}, [eventName, cb]);
return socket;
}

如果Index组件渲染不止一次,use套接字挂钩将再次运行。正如您在useSocket钩子中看到的,useEffect依赖于cb,并且每次运行Index组件时都会创建新的callback

我通过重构解决了这个问题,现在它可以工作了。

const SERVER_STATE = {
users: [ {userId: 123, socketId: 456} ]
} 

我在客户端生成一个带有UUID的userId,并将其保存在localStorage中。连接时,我会将其与socketId一起添加到SERVER_STATE.users,如果已经存在,我会更新socketId,以确保socketId在任何重复调用中保持最新状态。

断开连接时,我过滤用户数组。使用socketId获取userId,然后删除具有该userId的所有项目。

显然,我需要的总连接数是用户数组的长度。我可能会将其作为int缓存在SERVER_STATE中,这样我就不需要过多地计算它了。

最新更新