我有以下设置(仅为简洁起见,重要的位):
app.js
...
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
server.listen(port, function() {
console.log(`Server is listening on port: ${port}`);
});
io.on('connection', function (socket) {
console.log('connection');
});
const routes = require('./routes/index')(io, passport);
app.use('/', routes);
index.js(服务器)
router.get('/game/:id', isAuthenticated, (req, res) => {
if (req.id)
{
var game = Game.findOne({_id: req.id}, (err, obj) => {
io.on('getGameInfo', (socket) => {
io.emit('gameInfo', obj);
});
res.render('game', obj);
});
}
else
{
// Id not valid, do something
}
});
客户端:
const socket = io('http://localhost:3000');
socket.on('gameInfo', function(data) {
console.log(data);
}.bind(this));
socket.on('connect', () => {
socket.emit('getGameInfo');
});
所以基本上我想知道客户端连接后发出getGameInfo调用,并且已经在游戏路由中设置了getGameInfo监听器。但是当我从客户端发出getGameInfo时,服务器回调没有被命中。我不确定我是否遗漏了一些明显的东西,或者这是否是一个封闭问题,或者我是否正处于其中一天,或者我是否完全以错误的方式解决这个问题。
答案 0 :(得分:1)
这里有很多问题。我将首先展示在服务器上侦听传入的socket.io消息的正确方法:
io.on('connection', function (socket) {
// here's where you have a new socket and you can listen for messages
// on that socket
console.log('connection');
socket.on('gameInfo', (data) => {
socket.emit('gameInfo', obj);
});
});
一些问题:
在服务器上,您通过socket
对象而不是io
对象侦听消息。因此,您通常会在io.on('connection', ...)
处理程序中添加这些事件侦听器,因为您首先会看到新连接的套接字。
您几乎不想在Express路由处理程序中添加事件侦听器,因为它被多次调用。此外,在调用路由处理程序时,浏览器尚未收到该页面,并且尚未连接,因此即使这是一个可以执行操作的好地方,该页面仍未连接。
如果您只想将消息发送回一个连接,请使用socket.emit()
而不是io.emit()
发送。 io.emit()
向所有连接的客户广播,我认为这不是你想要的。
我建议您不要为客户端和服务器重载相同的消息名称,这意味着两种不同的东西,因为这会在阅读代码时导致混淆,或者您在客户端和服务器之间共享某些代码。你的客户真的发送了一个" getGameInfo"消息,然后您的服务器响应" gameInfo"包含gameInfo的消息。
如果在一个路由处理程序中,你希望.emit()
从该页面看起来像你试图做的那个套接字,那么你必须做一些工作来创建一个会话之间的链接当前页面和该页面的套接字。有很多方法可以做到这一点。如果您正在使用任何会话中间件,则可以在套接字连接时在会话中记录socket
。然后,从您的快速路线,您可以随时从会话对象中获取该套接字。