我很难把所有这三个放在一起,可能是因为我没有正确使用Express的路由概念。
我有一个带有事件更新的RabbitMQ队列。我们可以通过他们的身份识别这些事件。所以我想在一个关于事件的给定页面上,只是与其id相对应的更新。
队列:1316,1539,3486,3479,1316,3890,3479,...... - >无限期地从DB中提取。 www.example.com/event/1316 - >从队列中获取id为1316的消息 www.example.com/event/3479 - >从队列中获取id为3479
的消息当我加载第一个事件时,我的代码运行良好,但是当我在另一个窗口中加载第二个事件时,它会从两个事件中获取消息,如果我加载第三个事件,猜测是正确的,它会从三个事件中获取消息IDS。
app.js
var express = require('express')
, http = require('http');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server, { log: false });
require('./io')(io);
var amqp = require('amqp');
var rabbitMQ = amqp.createConnection({ host: 'localhost' });
rabbitMQ.on('ready', function() {
console.log('Connected to RabbitMQ');
io.sockets.on('connection', function (socket) {
console.log('Socket connected: ' + socket.id);
rabbitMQ.queue('offer', { autoDelete: false, durable: false, exclusive: false }, function(q) {
q.bind('#'); // Catch all messages
q.subscribe(function (message) {
obj = JSON.parse(message.data.toString());
//socket.broadcast.to(obj.id).emit('message', obj);
io.sockets.in(obj.id).emit('message', obj);
});
});
});
});
var routes = require('./routes')
, event = require('./routes/event');
app.get('/', routes.index);
app.get('/event/:id', event.index);
server.listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
io.js
var socketio = function (io) {
if (!io) return socketio._io;
socketio._io = io;
}
module.exports = socketio;
路由/ event.js
var io = require('../io')();
exports.index = function(req, res) {
io.sockets.on('connection', function (socket) {
socket.join(req.params.id);
});
res.render('event', { title: 'Event' });
};
谢谢!
答案 0 :(得分:2)
您收到的全部是因为join
但从未leave
房间。如果你从wiki看底部的Socket IO Rooms,它会提供io.sockets.manager.roomClients[socket.id]
作为获取套接字加入的房间列表的方法(我怀疑如果你已经将它包含在所有三个房间中)访问了所有三个链接)。
您可能想尝试浏览此房间列表和leave
任何不是当前房间的房间,并查看是否能解决问题。
好的,这有两个原因/解决方案。我刚刚测试了我的理论,它是有效的 - 您收到了join
编辑过的每个房间的消息,并且会继续这样做,直到您leave
为止。以下是选项:
leave
所有其他房间join
房间io.sockets.on('connection', function (socket) {
var room = req.params.id;
var roomKeys = Object.keys(io.sockets.manager.roomClients[socket.id]);
roomKeys.forEach(function(key) {
if (key === '' || key === '/' + room) return;
socket.leave(key.slice(1));
});
socket.join(room);
});
如上所述,我对此进行了测试。它有效。
message
事件,发送{room name}
事件您可以发出“{room name}”事件,而不是发出“消息”事件。您只需执行q.subscribe()
而不是包含io.sockets.in(obj.id).emit('message', obj);
的{{1}}回调,而您只有javascript客户端才会侦听该网页的事件类型(基于网址路径)。
我也测试了这个。它也有效。它也更简单(我认为),因为它只需要socket.emit(obj.id, obj);
回调中的.emit()
,这意味着您可以保存“房间管理”内容。
答案 1 :(得分:1)
尝试失败之后,我已经理解我做错了什么因为在路由器内使用io.sockets.on('connection')
复制了这个事件。所以最后,最简单的思维方式是正确的。
<强> app.js 强>
var room = '';
var roomHandler = function(req, res, next) {
if (req.path.match('event')) {
room = req.params.id;
}
next(); // Passing the request to the next handler in the stack.
}
io.sockets.on('connection', function (socket) {
socket.join(room);
});
rabbitMQ.on('ready', function() {
rabbitMQ.queue('offer', { autoDelete: false, durable: false, exclusive: false }, function(q) {
q.bind('#'); // Catch all messages
q.subscribe(function (message) {
obj = JSON.parse(message.data.toString());
io.sockets.in(obj.id).emit('message', obj);
});
});
});
app.get('/', routes.index);
app.get('/event/:id', roomHandler, event.index);