Socket.io 服务器仅接收客户端发出的多个事件中的第一个事件

问题描述 投票:0回答:1

我正在创建一个具有实时共享数据功能的反应,我使用

socket.io
express
作为后端,并使用
socket.io-client
将事件从客户端发送到后端

我有一些数据要在页面加载时发送到后端,但是当我使用数据从客户端发出事件并在后端侦听它们时,当记录到后端时,只有第一个发出的事件的数据才会在后端获取

console

这是我发出事件的前端代码

import { useEffect, useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import io from "socket.io-client";

const PORT = "http://localhost:3000";
const connectionOptions = {
  "force new connection": true,
  reconnectionAttempts: "Infinity",
  timeout: 10000,
  retries: 3,
  transport: ["websocket"],
};

const server = io(PORT, connectionOptions);

function App() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    server.emit("start");
    server.emit("end");
  }, []);

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.jsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  );
}

export default App;

这是我监听事件的后端代码

import express from "express";
import http from "http";
import { Server } from "socket.io";
import cors from "cors";

const port = process.env.PORT || 3000;
const app = express();
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"],
  },
});

io.on("connection", (socket) => {
  console.log("Connected");

  socket.on("start", () => {
    console.log("start");
  });

  socket.on("end", () => {
    console.log("end");
  });

  socket.on("disconnect", () => {
    console.log("Disconnected");
  });
});

server.listen(port, () =>
  console.log(`server is running on http://localhost:${port}`)
);

app.get("/", (req, res) => {
  res.send("MathCollab server");
});

加载网页时,我希望在后端控制台中看到以下日志

Connected
start
end

但我在控制台中看到的只是

Connected
start

我在代码中忽略了什么

reactjs node.js express server socket.io
1个回答
0
投票

这可能是因为您从客户端发出事件的方式所致。事件很可能是异步发出的,并且由于开始和结束事件几乎同时发出,因此会发生竞争条件,服务器端仅正确接收其中一个事件。
因此,您可以确保仅在结束事件被确认后才发出开始事件,而不是依赖于时间。实现此目的的一种方法是利用 Socket.IO 中的确认。

useEffect(() => {
  server.emit("start", () => {
    // acknowledgment callback for start event
    server.emit("end"); // Emit end event after start event is acknowledged
  });
}, [])

并获取服务器端代码来发送确认,

socket.on("start", (callback) => {
  console.log("start");
  callback(); // Acknowledge start event
});

socket.on("end", () => {
  console.log("end");
});

这种方法将确保只有在服务器确认开始事件之后才会发出结束事件,从而确保事件的顺序。
删除重试选项可能会解决该问题,因为它可能会改变事件发射的时间,使它们更加连续而不是同时发生。

© www.soinside.com 2019 - 2024. All rights reserved.