我正在创建一个具有实时共享数据功能的反应,我使用
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
我在代码中忽略了什么
这可能是因为您从客户端发出事件的方式所致。事件很可能是异步发出的,并且由于开始和结束事件几乎同时发出,因此会发生竞争条件,服务器端仅正确接收其中一个事件。
因此,您可以确保仅在结束事件被确认后才发出开始事件,而不是依赖于时间。实现此目的的一种方法是利用 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");
});
这种方法将确保只有在服务器确认开始事件之后才会发出结束事件,从而确保事件的顺序。
删除重试选项可能会解决该问题,因为它可能会改变事件发射的时间,使它们更加连续而不是同时发生。