我的套接字 io 正在工作,但是当我添加新数据时,它不是实时的,ReactJS,Express,Mongoose

Posted

技术标签:

【中文标题】我的套接字 io 正在工作,但是当我添加新数据时,它不是实时的,ReactJS,Express,Mongoose【英文标题】:My socket io is working but when I add new data, it's not real time, ReactJS, Express, Mongoose 【发布时间】:2021-07-26 08:21:50 【问题描述】:

我真的无法在互联网上找到答案,所以我想在这里问。我的套接字 io 工作,因为我可以在页面第一次加载时显示来自后端的数据,但是当我添加新数据时,我仍然需要刷新我的页面以便更新我的前端,它还不是实时的。我使用 express router/rest api 将新数据添加到数据库中。而且我还想问,为什么我必须在我的前端添加 transports: ['websocket', 'polling', 'flashsocket'] ?我看到其他人在没有运输的情况下这样做,但是当我这样做时会发生 CORS 错误。谢谢!

这是我在文件 App.js 上的 React JS 代码。 (我没有包含 const App = () => ....,但是 state 和 useEffect 在 const App 里面)

import io from "socket.io-client";
const socket = io("http://localhost:3001",  transports: ['websocket', 'polling', 'flashsocket'] );

const [rooms,setRooms] = useState([]);

useEffect(() => 
    socket.emit("rooms");

    socket.on("rooms", rooms=> 
        setRooms(rooms);
    )
,[])

这是我的 app.js (node/express)

const http = require('http').createServer(app);
const io = require("socket.io")(http);

const viewRooms = require("./events/rooms");

const onConnection = (socket) => 
     viewRooms(io,socket);


io.on("connection",onConnection);

这是我的活动文件夹中的 rooms.js 文件

const Rooms= require("./../models/Rooms");

module.exports = (io,socket) => 
    const view = () => 
        Rooms.find()
        .then(rooms=> 
            io.emit("rooms",rooms);
        )

    
    socket.on("rooms",view);
 

我用来向数据库添加数据的提交函数

const submitHandle = (e) => 
    e.preventDefault();

    const formData = new FormData();
    formData.append('name',addForm.name);
    addForm.description.forEach((val,key) => 
        formData.append("article[" + key + "]" + "[" + Object.keys(val) + "]",val.paragraph);
    )
    addForm.images.forEach(val => 
        formData.append("image",val);
    )
    formData.append('date',addForm.date);

    let token = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwNDU2ZmNhNTI3ZTdhMGEwODY0NjVjNSIsImlhdCI6MTYxODI3NzIyNX0.w6eBHJC72xo-NRPtzJ3gKu_hIY70eCk_-K3-pkO4bAc";        

    fetch("http://localhost:3001/rooms/upload",
        method : "POST",
        body : formData,
        headers : 
            "Authorization" : token
        
    )
    .then(data => data.json())
    .then(rooms=> 
        console.log(rooms);
        alert(rooms.message);
    )

这是我的特快路线上的代码(帖子)

const router = require("express").Router();
const Rooms = require("./../models/Rooms ");
const auth = require("./../authorization");
const passport = require("passport");
const multer = require("multer");
require("./../passport-setup");

// IMAGE DESTINATION AND FILENAME
const storage = multer.diskStorage(
    destination : (req,file,cb) => 
        cb(null,"public/images")
    ,
    filename : (req,file,cb) => 
        cb(null, Date.now() + "-" + file.originalname)
    
)

// upload
const upload = multer( storage : storage);

// upload rooms
router.post("/upload",upload.array("image",10),passport.authenticate("jwt",session : false),auth,(req,res,next) => 

let allDescription = req.body.description;

req.body.images = req.files.map(file => 
    return(
        
            roomName : req.body.name,
            image : "/public/" + file.filename
        
    )
)
Rooms .create(req.body)
.then(rooms=> 
    res.send(
        message : "Rooms uploaded!",
        success : true,
        rooms
    )
)
.catch(next);

)

【问题讨论】:

【参考方案1】:

对于您问题的第一部分,我们必须查看更多日志信息,才能确切了解发生了什么。您的客户端 socket.emit("news"); 似乎可能在您的 socket.io 连接完全建立之前发生得太早,并且可能在服务器准备好接收传入请求之前发生。您可以完全记录每个 socket.io 事件,并可能确定发生了什么。

我还想问,为什么我必须在前端添加 transports: ['websocket', 'polling', 'flashsocket'] ?

如果您没有将 websocket 列为第一个传输,那么 socket.io 会以一些 http 轮询请求开始,并且这些 http 请求受 CORS 约束。 webSocket 传输不受 COR 的约束,因此如果您强制它首先使用它,那么就没有 COR。仅供参考,socket.io 使用的 http 轮询仅用于检测不支持或阻塞 webSocket 传输的情况。如果您不关心这一点,那么您真的可以在前端执行此操作:

 transports: ['websocket'] 

或者,您可以从客户端完全删除传输选项,然后在您的服务器上实现对 COR 的支持,以便允许 COR 轮询请求。

【讨论】:

对不起,我没有得到您对我问题第一部分的回答。我只有 1 个 socket.io 事件,因为我目前正在学习如何使用它。如何知道我的客户端:socket.emit("news",news) 是否发生得太早?在第一次加载页面时,我的套接字 io 工作,它可以从数据库中获取数据并更新我的状态,但是当我使用快速路由器/api 添加新数据时,我的 socket.io 不能实时工作,所以我有再次刷新我的页面。现在,我刚刚在使用 express api(当然在前端)添加数据的函数上添加了 socket.emit("news",news),它就可以工作了。 那么我必须在连接到我的 express api 的每个函数上添加 socket.emit("news",news) 吗?还是我做错了什么? @benjamin_nmn - 当您执行 const socket = io("http://localhost:3001", transports: ['websocket', 'polling', 'flashsocket'] ); 时,它不会立即连接 - 这需要一些时间。事实上,当客户端连接准备好时,套接字上会发生一个connect 事件。我猜你可能正试图在套接字准备好之前发送它。 如何确保在通过套接字发送之前,服务器已准备就绪?为什么它在第一次加载时有效,但在我使用 rest api 向数据库添加新数据时无效? @benjamin_nmn - 你在展示你的休息 api 代码吗?我没看到。无法回答有关我们看不到的代码的问题。

以上是关于我的套接字 io 正在工作,但是当我添加新数据时,它不是实时的,ReactJS,Express,Mongoose的主要内容,如果未能解决你的问题,请参考以下文章

React 和 Socket.io:能够获取初始数据 - 但是当有新帖子出现时视图不会更新

React Native 中的套接字 io

iOS didAcceptNewSocket 期望不同的端口号

iOS - 移动视图时界面元素重叠

django:在添加新照片时删除以前的照片

将 Socket.io 与 Sequelize 一起使用