簡體   English   中英

套接字 IO 發出事件兩次

[英]Socket IO emit events twice

情況:

我正在設置一個帶有 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 事件。

我想要什么:我希望套接字只處理這些事件一次。

看起來你的組件渲染了兩次,所以調用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*/);
};

在 index.js 文件中創建套接字並作為道具傳遞給根應用程序組件,如下所示:-

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;

我有一個類似的問題。 我通過在我的功能組件中編寫一個 useEffect 來解決它,該 useEffect 打開套接字 onMount(和 onUpdate)但關閉 SOCKET ON UNMOUNT。

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

我有同樣的問題,我解決了。

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

正如您在此處看到的,您必須使用 React 提供的useEffect function。 接下來,您必須在useEffect function 中附加以下代碼,以防止兩次收到相同的消息。 如果您有 4 種監聽方法,則必須將代碼附加 4 次以防止每種方法出現該問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM