Socket.io:如果在快速路由中使用,事件会触发两次

Posted

技术标签:

【中文标题】Socket.io:如果在快速路由中使用,事件会触发两次【英文标题】:Socket.io: Events firing twice if used inside an express route 【发布时间】:2020-04-03 10:56:14 【问题描述】:

我正在使用 socketio 开发一个聊天应用程序。我遇到的问题是,如果我将io.on('connection', ..) 块放在快速路线app.get('/chat') 之外,一切正常,但是当我将它放在路线/chat 内时。连接内的所有内容都会触发两次。

server.js

 // On new connection
 io.on("connection", socket => 
      console.log('Socket ID: ' + socket.id);
      // I want the user object (inside /chat route) to be available here..
 )

// @route:chat
app.get("/chat", auth, async (req, res) => 
    const user = User.findbyId(req.userId);
    // socket.io part moved outside the route

    res.render('chat', )
)

第一次请求时输出到/chat

Socket ID: 5e82d1a21c9d4400003e9bce

第二次请求时输出到/chat

Socket ID: 5e82d1a21c9d4400003e9bce --> this is repeating
Socket ID: 5e82d1a21c9d4400003e9bc4

如果我继续请求/chat,以此类推。

知道如何解决这个问题吗?

【问题讨论】:

这是因为您正在为 on('connection') 注册两个事件处理程序。把它放在路线之外。 是的,您正在回答标题中的问题... 我想在路由中使用io.on("connection") @i.brod 我在哪里注册两个事件处理程序? 在您的 GET /chat 路由中。每次请求到达此路由时,您都在为 io.on('connection') 注册另一个处理程序 【参考方案1】:

通常,socketIO 操作不应依赖于快速路由。如果您希望用户加入 socketIO 连接,则应通过 SocketIO 的事件处理程序来完成。如果您想将“用户”与该套接字关联,您的前端应该启动连接,并将一些身份传递给 SocektIO。

我不知道你的应用程序如何处理身份验证,但一种常见的做法是向 SocketIO 连接建立传递一个令牌:

const socket = IO.connect('http://localhost:8000', 
    query: 
      token//This token will be available on the server.
    
  );

那么在你的服务器中:

const middleware = async (socket,next)=>
    const token = socket.handshake.query.token;//Now you have the user token, which presumably contains the user ID.

    const verifiedUser = await getUserByToken(token);//Let's say this returns a user object, if the token is valid, false if not.
    // Let's assume that behind the scenes this function also calls User.findbyId(id);

    if(verifiedUser)
        socket.userObject = verifiedUser;//You can place the userObject on the token object, to be used later.
        next()//Will allow the "connection" event to proceed.
    else
        next(new Error('INVALID_CREDENTIALS'))//Will cause the on("error") event to fire in the front-end, passing this error.
        //The on("connection") event here will not fire.
    


io.use(middleware)

io.on('connection', async (socket) =>  

    //This runs only if middleware is "successful".


)

我不知道这是否真的回答了您的问题,但它是套接字-用户关系的一个示例。

【讨论】:

以上是关于Socket.io:如果在快速路由中使用,事件会触发两次的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Express 4 路由中使用 socket.io 向连接的套接字发出事件?

Socket.io 消息事件多次触发

如果使用 Node.js 在 Socket.io 中的应用程序中登录功能,则为特定用户发出事件

Socket.io 断开事件和相关闭包的垃圾收集

当我的网站在多个窗口中打开时,在实时事件中打开 window.open(使用 socket.io)

如何检测Socket IO中的重新连接事件