发送 15 条消息后,带有套接字的 React 聊天应用程序变慢

Posted

技术标签:

【中文标题】发送 15 条消息后,带有套接字的 React 聊天应用程序变慢【英文标题】:React chat application with socket slows down after 15 messages are sent 【发布时间】:2022-01-07 11:11:08 【问题描述】:

我是一名新开发人员,正在尝试制作一个相当强大的 React 项目,在这个项目/网站中,有一个带有一些自定义选项卡的页面,其中一个选项卡是聊天。此聊天使用套接字与服务器进行通信。问题是在发送了大约 15-20 条消息后,任何收到聊天消息的客户端都会冻结很长一段时间。这是我在我的反应客户端中实现套接字的方式。

我有一个名为 socket.js 的实用程序文件:

import io from "socket.io-client";
const SOCKET_URL = "http://localhost:3001";
export const socket = io(SOCKET_URL,  transports : ['websocket'] );

在使用套接字的反应组件内部:

import socket from "../../utils/socket";

// This code runs (I think) only when the chat state variable changes or when I receive a socket update from the server
useEffect(()=>
    socket.on("chat msg sent",(chatObj)=>
        setChat([...chat,chatObj])
    )
,[socket,chat])

// This code is being run when someone sends a chat
const sendChat = (msg) => 
    const socketObj = name:props.userState.username, content:msg, id,
    console.log(socketObj);
    socket.emit("sending chat msg",socketObj)
    const clientObj = name:props.userState.username, content:msg
    setChat([...chat,clientObj]);

这是这个反应组件返回的内容:

return (
    <div className="container-fluid p-0 m-0 border border-3 border-danger">
        <div className="row p-0 m-0">
            <div className="col-3 border border-primary border-4"><h1></h1></div>
            <div className="col-7 border border-info border-4"></div>
            <div className="col-2 border border-success border-4">
                <div className="tab">
                    <button className="tablinks" onClick=()=>setTab('chat')>Chat</button>
                    <button className="tablinks" onClick=()=>setTab('characters')>Char</button>
                    <button className="tablinks" onClick=()=>setTab('compendium')>Comp</button>
                    <button className="tablinks" onClick=()=>setTab('settings')>Sett</button>
                </div>
                <div className="tab-content">
                    tabContent
                </div>
            </div>
        </div>
        <Character/>
    </div>
    );

选择聊天选项卡时,TabContent状态变量设置为此:

setTabContent(
    <div>
        <ul className="chat">
            chat.map((entry)=>
                return(
                    <li>
                        <h6>entry.name</h6>
                        <p>entry.content</p>
                    </li>
                )
            )
        </ul>
        <form onSubmit=(e)=>
            e.preventDefault();
            sendChat(chatInput);
            setChatInput('');
        >
            <input className="" value=chatInput onChange=(e)=>setChatInput(e.target.value)/>
        </form>
    </div>
)

在后端,我有一个名为 socketServer.js 的文件,该文件包含任何套接字连接,它只是一个导出到主服务器文件的函数。 socketServer.js:

exports = module.exports = function (io) 
    io.on('connection', function (socket) 
        io.emit('greeting', 'welcome to our site!');

        socket.on('join campaign room',(id)=>
            socket.join(id);
            console.log("joining the campaign room", id);
        );
        
        socket.on('sending chat msg', (socketObj)=>
            console.log("cool beans", socketObj);
            const chatObj = name:socketObj.name, content:socketObj.content
            socket.broadcast.to(socketObj.id).emit('chat msg sent',chatObj);
        );
    );

总体而言,这一直有效,直到发送了太多消息,然后对于任何接收消息的人来说都会变得非常慢。我不认为这是后端的问题,我认为这与通过套接字更新的反应状态变量有关,但我可能是错的。

【问题讨论】:

如果我的回答解决了您的问题@Carsdan Dvorachek,请记住将其设置为接受的答案。 【参考方案1】:

每次您获得由setChat() 设置的新chat 变量时,您的useEffect 都会建立与socket.io 的新连接。因此,在 15 条消息之后,您已经为套接字事件 sending chat msg 设置了 15 个侦听器。同时你不会在 useEffect 的清理中移除之前的监听器。

你可以试试这个,只为套接字事件设置一个监听器

import socket from "../../utils/socket";

// This code runs (I think) only when the chat state variable changes or when I receive a socket update from the server
useEffect(()=>
    const setChat = (chatObj) => 
        setChat(oldChat => [...oldChat, chatObj])
    

    socket.on("chat msg sent", setChat)

    return () => soket.removeListener("chat msg sent", setChat)
,[socket])

【讨论】:

以上是关于发送 15 条消息后,带有套接字的 React 聊天应用程序变慢的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 Websocket 在发送消息之前等待连接和就绪状态更改

如何在套接字上不断接收用户的消息?

C TCP套接字,带有文件发送的回显服务器,发送文件后挂断

RocketMQ消息发送流程

使用 React 和 Socket.io 的聊天应用程序在发送太多消息后挂起

带有线程池服务器python的套接字