当前位置: 首页 > 知识库问答 >
问题:

使用mern stack和socket的聊天应用程序。io在发送超过20条消息后速度变慢

左丘楷
2023-03-14

我正在使用MERN堆栈和socket.io构建一个实时聊天应用程序。在发送大约20条消息后,该应用程序变得很慢,当其他用户仅在收到发送的消息后才发送另一条消息时,用户无法编写和发送消息。这是我的聊天组件

import React, {useEffect, useRef, useState} from 'react';
import Messages from "../Messages/Messages";
import axios from 'axios';
import io from "socket.io-client";

const socket = io('http://localhost:5000/')
function Chat(props) {
    const [messages, setMessages] = useState([])
    const [input, setInput] = useState("")
    useEffect(() => {
        axios.get("http://localhost:5000/")
            .then((res) => {
                setMessages(res.data)
            })
           
        return () => {
            socket.disconnect();
        }
    }, [])
    useEffect(() => {

        socket.on('msgSent', (data) => {
            setMessages([...messages, data])
        })
    }, [messages])
    const renderMessages = () => {
        return (
            messages.map( (message) => {
                return (
                    <Messages key={message._id} sender={message.sender.firstName.concat(message.sender.lastName)}
                              messageText={message.messageText}
                               />
                )
            })
        )
    }
    const sendMessage = (e) => {
        e.preventDefault()
        const message = {
            messageText: input,
        }
        axios.post("http://localhost:5000/", message)
            .then(res => {
                setMessages([...messages, res.data])
                socket.emit('msgSent', res.data)
            })         
    }
    return (       
                {renderMessages()}
                <form onSubmit={(e) => sendMessage(e)}>
                    <input type="text" placeholder="type a message" value={input}
                           onChange={(e) => setInput(e.target.value)}/>
                    <button type="submit"></button>
                </form>                
    );
}
export default Chat;

这是我的服务器端代码

const express = require("express")
const app = express()
const mongoose = require('mongoose')
const homeRoot = require("./Routes/homeRoot")
const http = require('http').Server(app);
const io = require('socket.io')(http)    
//listening
http.listen(5000, () => {
    console.log("hello from server")
})

//Routes
app.use("/", homeRoot)

//socket
io.on('connection', (socket) => {
    socket.on('msgSent',(data)=>{
        socket.broadcast.emit('msgSent',data)
    })
});

//Db connection
mongoose.connect("mongodb+srv://@cluster0.agiog.mongodb.net/myFirstDatabase?retryWrites=true&w=majority")

这是homeRoot,我在这里获取信息

const express = require("express")
const Router = express.Router()
const Messages = require("../Models/messageModel")
const Users = require("../Models/userModel")
const auth = require("../auth")
Router.get("/",auth,async(req,res)=>{
    try {
        const messages = await Messages.find().populate("sender","firstName lastName")
        res.status(200).send(messages)
    }catch (e) {
        res.status(404).send("messages not found")
    }
})

Router.post("/",auth,async(req,res)=>{

    const user = await Users.findOne({_id:req.userId})
    const message = new Messages({...req.body,sender:user})
    try {
        const savedMessage = await message.save()
        res.status(201).send(savedMessage)

    }catch (e) {
        res.status(404).send("error occured")
    }
})

module.exports = Router

共有2个答案

秋阳旭
2023-03-14

亚德内什给出的答案有一个小陷阱。让我解释一下。

这种模式还在继续。。

useEffect(() => {
  socket.on('msgSent', (data) => {
   setMessages([...messages, data])
  });

  return () => {
    socket.off("msgSend");
  };
}, [messages]);

问题是,您不希望每次更新MessageList时都创建一个新的socket.io侦听器。您应该始终在组件的生命周期内为一个事件创建一个侦听器。因为一旦创建了socket.on侦听器,那么它在侦听该事件首次发生后不会被销毁,它只是再次侦听该事件。

因此,这样的侦听器必须创建一次。在您的情况下,它应该在安装组件时创建。

因此,请使用[],空列表作为useEffect的第二个参数。这个挂钩相当于componentDidMount。

useEffect(() => {
  socket.on('msgSent', (data) => {
   setMessages([...messages, data])
  });

  return () => {
    socket.off("msgSend");
  };
}, []);
桂梓
2023-03-14
useEffect(() => {
   socket.on('msgSent', (data) => {
   setMessages([...messages, data])
  })

return{
 socket.off("msgSent");
 }
}, [messages])

你需要使用插座。off(),如上例所示。

 类似资料:
  • 我正在尝试使用node.js、socket.io和express制作一个简单的聊天应用程序。但是,如果我单击main.jade文件中的send按钮,页面会刷新,并且不会出现任何消息。我在Firebug中也遇到这个错误: 加载页面时,与ws:/127.0.0.1:3000/socket.io/?eio=2&transport=websocket&sid=d_hnmpdxhed-j7lraaah的连接

  • 我是节点js&socket.io的新手。给我一个如何解决这个问题的架构指南。提亚。 我的app.js代码:

  • 我正在用插座找一个指定的房间。io,但其给出的错误为“未定义房间”。下面是我的代码。谁能帮忙吗?或者解释什么问题 });

  • 我的问题是,我仍然可以在客户端之间发送消息(客户端到客户端),但发送两三次后,消息不再显示给收件人。 因此,基本上每当客户机希望向另一个客户机发送消息时,该消息首先被发送到服务器。但正如您从我的编码中注意到的,我是以对象的形式发送服务器数据的。例如: 当您发送消息时,类型是“message”。当服务器接收对象时,它检查接收数据及其类型。例如: 如果类型是“message”,那么它会向特定的客户端发

  • 我目前有2个屏幕,一个所有的消息屏幕,其中包括我参与的所有聊天和一个聊天屏幕,这是实际的聊天本身。 在我的聊天屏幕中,我成功地实现了套接字,所以当两个用户同时在聊天屏幕上时,消息就会实时交换。 客户 ChatScreen.js AllMessagessCreen.js

  • 是否可以在不打开应用程序的情况下发送whatsApp消息,在后台发送,就像使用以下方式发送短信: 如果是,怎么做?我尝试的代码打开了应用程序(意图): 或者是否可以打开应用程序,发送消息到给定的地址,然后关闭它? 谢谢!