Socket.io页面刷新时创建多个连接问题求助
嘿,这个问题我太熟了!你这是踩了Socket.io事件重复绑定的典型坑——每次用户刷新页面,你的路由处理器都会重新执行一遍io.on('connection', ...),相当于给connection事件多绑了一个监听器。下次有新连接进来时,所有绑定的监听器都会触发,所以你才会看到“连接数”越来越多,本质是同一个连接触发了多次回调。
解决办法其实很简单,分两步来:
把
connection事件的监听移到路由外面,只初始化一次
Socket.io的io实例是全局的(或者说在服务器启动时创建的),应该在服务器启动的入口文件(比如app.js或者server.js)里绑定connection事件,而不是每次请求都绑。比如:// 在服务器启动文件里,创建io实例后直接绑定事件 const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const app = express(); const server = http.createServer(app); const io = socketIo(server); // 这里只绑定一次connection事件,服务器启动后就不会再重复绑定了 io.on('connection', function(socket){ console.log('新客户端连接:%s', socket.id); // 在这里写你的socket逻辑,比如监听聊天消息、断开事件等 socket.on('chat message', function(msg){ io.emit('chat message', msg); }); socket.on('disconnect', function(){ console.log('客户端断开连接:%s', socket.id); }); }); // 然后再挂载你的路由 const chatRouter = require('./routes/chat'); app.use('/', chatRouter); server.listen(3000, () => { console.log('服务器运行在http://localhost:3000'); });修改你的聊天路由,只负责渲染页面
路由里不要再处理io的connection事件了,只需要完成页面渲染和用户身份验证的逻辑就行:/* GET home page. */ router.get('/', accessControl.ensureAuthenticated, function(req, res, next) { // 这里只需要渲染聊天室页面,不用再碰io的事件绑定 res.render('chatroom'); // 替换成你实际的页面模板名称 });
为什么原来的代码会出问题?
每次用户访问/路由(包括刷新页面),都会触发router.get里的回调函数,每次都会执行io.on('connection', ...)——这就相当于给同一个事件反复添加新的监听器。当有新的socket连接进来时,所有之前绑定的监听器都会被触发一次,看起来就像是“新增了连接”,但实际上是同一个连接触发了多次逻辑,会导致聊天消息重复发送、状态异常等问题。
额外提醒:如果需要在路由里和Socket.io交互(比如给特定用户发消息),可以通过req.app.io获取io实例,但绝对不要在请求处理器里绑定事件,因为每次请求都会重复绑定,只会让问题越来越严重。
内容的提问来源于stack exchange,提问作者bakely
相关产品推荐
相关产品推荐

