javascript 套接字IO发出两次事件

2wnc66cl  于 2023-01-19  发布在  Java
关注(0)|答案(4)|浏览(112)

情况:

我正在用www.example.com设置一个快速服务器socket.io,用ReactJS设置一个客户端。

//... another requirement
const socket = require("./socket");

const app = express();
const server = http.createServer(app);
const port = process.env.PORT || 3000;

//... some parsers ...

routes(app);
socket(server);

server.listen(port);
console.log("Server started on: " + port);

这是我的插座

const socketIO = require("socket.io");

const socket = server => {
  const io = socketIO(server);
  const chat = io.of("/chat");
  chat.on("connection", client => {
    console.log("User started chat!");
    client.on("disconnect", () => {
      console.log("User left chat!");
    });

    client.on("sendMessage", msg => {
      const { id, text } = msg;
      console.log(id + " says: " + text);
      client.broadcast.emit("incomingMessage", {
        //... response data
      });
    });
  });
};

在客户端中,聊天页面组件将处理向套接字发送消息和从套接字接收消息:

//_ChatBox in Chat Page
const _ChatBox = (/*props*/) => {
  const chat = io("http://localhost" + ":3000/chat");

  chat.on("incomingMessage", message => {
    console.log("Receive message");
    //...handle income message
  });

  const sendMessageToSocket = (data) => {
    chat.emit("sendMessage", data);
  };

  return ( /*JSX*/);
};

问题:

每次用户访问聊天页面时,套接字将接收连接事件并将User started chat!记录到控制台一次,但实际上,它已记录两次,这意味着套接字已处理连接事件两次。
当_ChatBox接收到消息时,它将记录Receive message并显示该消息,但它所做的是记录两次并显示两次消息,这也意味着套接字已发出incomeMessage事件两次。

**我想要的:**我希望套接字只处理这些事件一次。

anauzrmj

anauzrmj1#

看起来您的组件呈现了两次,因此调用const chat = io("http://localhost" + ":3000/chat");两次,给出两条连接消息。
你可以使用useEffect()钩子只在第一次渲染时连接。传入一个空数组作为第二个参数意味着效果只会被调用一次:

const _ChatBox = (/*props*/) => {

  useEffect(()=>{
     const chat = io("http://localhost" + ":3000/chat");

    chat.on("incomingMessage", message => {
      console.log("Receive message");
      //...handle income message
     });

     const sendMessageToSocket = (data) => {
      chat.emit("sendMessage", data);
     };
   }, []);

  return ( /*JSX*/);
};
kadbb459

kadbb4592#

在index.js文件内创建套接字,并将其作为prop传递给根应用程序组件,如下所示:-

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import socketIOClient from "socket.io-client"
var socket = socketIOClient('http://localhost:9000');
ReactDOM.render(
  <React.StrictMode>
     <App socket={socket} />
  </React.StrictMode>,
document.getElementById('root')
);

现在使用此套接字发出如下事件:-

import React from "react"
import './App.css';
class App extends React.Component {
componentDidMount() {
   this.props.socket.emit('test')
}
render() {
  return (
     <div>
        hello
    </div>
  );
}
}
export default App;
vxbzzdmp

vxbzzdmp3#

我也遇到过类似的问题,我通过在函数组件中编写一个useEffect来解决这个问题,这个useEffect在挂载(和更新)时打开socket,但在卸载时关闭SOCKET。

useEffect(()=>{
    const socket = io("http://localhost:3000")
    socket.on(userId, (arg) => {
        //stuff
    }); 
    return () => socket.emit('end'); //Close socket on UNMOUNT
})
ryoqjall

ryoqjall4#

我也有同样的问题,我解决了。

return() => {
     socket.off("whatever_you_named").off();
 }

here所示,您必须使用React提供的useEffect函数。接下来,您必须在useEffect函数中附加以下代码,以防止两次接收相同的消息。如果您有4个侦听方法,则必须将这些代码附加4次,以防止每个方法出现此问题。

相关问题