Socket.IO 在一个房间内多次发射(与 React.js 一起使用)

Posted

技术标签:

【中文标题】Socket.IO 在一个房间内多次发射(与 React.js 一起使用)【英文标题】:Socket.IO emits multiple times in a room (Using with React.js) 【发布时间】:2021-09-09 08:46:34 【问题描述】:

我有一个 react 应用程序,它允许多个用户加入一个房间,然后服务器随机选择一个用户,然后将所选用户的用户名发送给房间里的每个人。但问题是服务器多次发出同一个事件(发出的次数等于房间内的用户数)。

这是来自服务器的发出事件的代码:

socket.on("selectNextPlayer", roomid => 
        const selectedIndex = Math.round(Math.random()*rooms[roomid].participants.length);
        const selectedUsername = rooms[roomid].participants[selectedIndex];
        io.to(roomid).emit("setSelectedPlayer",selectedUsername); // THIS EVENT
        connectedUsers[selectedUsername].emit("myTurn");
    )

这是react客户端中监听事件的代码:

const socket = socketIOClient("http://127.0.0.1:8080");

useEffect(() => 
        if(isRoomOwner)
            socket.emit("createNewRoom", username,roomid);
        else 
            socket.emit("joinNewRoom", username,roomid);
        

        //Get all participants
        socket.on("allParticipants", (allparticipants, roomOwner) => 
            setParticipants(allparticipants);
            setOwner(roomOwner);
        )
        //Start/Stop Game
        socket.on("gameStatusChanged", gameStatus => 
            setGameStarted(gameStatus);
            //Select Next Player
            socket.emit("selectNextPlayer",roomid);
        )
        //set selected player
        socket.on("setSelectedPlayer", selectedPlayer =>  //HERE
            setSelectedPlayer(selectedPlayer);
            setChats(prevChats => ([...prevChats,`Next player is $selectedPlayer`]))
        )
        //On my turn show truth/dare buttons
        socket.on("myTurn", () => 
            setIsMyTurn(true);
        )
    ,[]);

问题是元素Next player is $selectedPlayer被多次添加到chats数组中,该数组存储在一个状态中。

我尝试将const socket = socketIOClient("http://127.0.0.1:8080"); 移动到另一个文件并使用import socket from '../services/socket'; 在顶部导入它,但没有成功。

编辑:(感谢@Tushar)

selectNextPlayer 被多次调用。

socket.on("gameStatusChanged", gameStatus => 
            setGameStarted(gameStatus);
            //Select Next Player
            socket.emit("selectNextPlayer",roomid);
        )

此函数调用发出 selectNextPlayer 函数。此函数监听 gameStatusChanged 事件并调用发出一个新的 selectNextPlayer 函数。

socket.on("startGame", roomid => 
        console.log("SELECT START GAME CALLED");
        io.to(roomid).emit("gameStatusChanged", true);
    )

此事件会发出 gameStatusChanged 事件,但它只被调用一次。那么为什么 selectNextPlayer 会被多次调用呢?

【问题讨论】:

gameStatusChanged 是如何调用的。检查它是否只被调用一次。您可以在 selectNextPlayer 上方添加一个控制台,以确认它被调用一次。 @TusharShahinOh yes selectNextPlayer 被多次调用 这就是你想要的吗?因为那是触发错误发射的事件。 @TusharShahi 等一下让我更新问题 @TusharShahi 我编辑了问题,请立即检查 【参考方案1】:

问题是

socket.on("gameStatusChanged", gameStatus => 
    setGameStarted(gameStatus);
    //Select Next Player
    socket.emit("selectNextPlayer",roomid);
)

在客户端,因此对于每个客户端,都会触发 "selectNextPlayer" 事件。因此,要将 socket.emit("selectNextPlayer",roomid); 这个移动修复到其他地方,对我来说,就是将它移动到发出 startGame 事件的同一个考试事件处理程序。


                username == owner && !gameStarted &&
                <button 
                    onClick=() => 
                        socket.emit("startGame",roomid);
                        socket.emit("selectNextPlayer", roomid);
                    
                >
                    Start Game
                </button>
            

【讨论】:

以上是关于Socket.IO 在一个房间内多次发射(与 React.js 一起使用)的主要内容,如果未能解决你的问题,请参考以下文章

在 NestJs 中使用 Socket IO 加入和发射到房间

Socket IO AngularJS(1.x) 工厂注入多次发射

如何使用 socket.io-p2p 在房间内建立对等连接?

套接字 io 不向房间发送消息

使用 socket.io 时如何获取房间内的客户端数量?

如何更新房间内所有客户端的套接字对象? (socket.io)