3

Expressを使用したルーティングの概念が適切に理解されていないためか、これら3つすべてをまとめるのに苦労しています。

イベントが更新されたRabbitMQキューがあります。これらのイベントはIDで認識できます。そのため、イベントに関する特定のページにアクセスしたいと思います。そのIDに対応する更新だけです。

キュー:1316、1539、3486、3479、1316、3890、3479、...->DBから無期限にフィードします。www.example.com/event/1316->ID1316のメッセージだけをキューから取得しますwww.example.com/event/3479->ID3479のメッセージだけをキューから取得します

私のコードは最初のイベントをロードするとうまく機能しますが、別のウィンドウで2番目のイベントをロードすると、両方のイベントからメッセージを取得します。3番目のイベントをロードすると、3つのIDからメッセージを取得します。

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' });
};

ありがとう!

4

2 に答える 2

2

joinあなたはあなたが部屋を決して持っていないので、あなたはそれらすべてを受け取っていますleave。Wikiの下部にあるSocketIORoomsを見ると、ソケットが参加している部屋のリストを取得する方法として提供io.sockets.manager.roomClients[socket.id]ています(3つのリンクすべてにアクセスした場合は、3つすべてが含まれると思います)。

この部屋のリストとleave現在の部屋ではない部屋のリストを調べて、問題が解決するかどうかを確認することをお勧めします。

編集

さて、これには2つの理由/解決策があります。私はちょうど私の理論をテストしました、そしてそれは有効です-あなたはあなたがjoin編集した各部屋のためにメッセージを受け取ります、そしてあなたが彼らになるまでそうし続けますleave。だからここにオプションがあります:

1.他のすべての部屋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);
});

言ったように、私はこれをテストしました。できます。

2.イベントを送信せず、messageイベントを送信し{room name}ます

'message'イベントを発行する代わりに、'{roomname}'イベントを発行することができます。q.subscribe()を含むコールバックの代わりにio.sockets.in(obj.id).emit('message', obj);、あなたはただそうするでしょう、socket.emit(obj.id, obj);そしてあなたはjavascriptクライアントにそのページのイベントタイプ(URLパスに基づく)だけをリッスンさせるでしょう。

私もこれをテストしました。それも動作します。また、コールバックでのみ必要なため、より簡単です(私は思います)。.emit()これq.subscribe()は、「部屋の管理」のものを保存することを意味します。

于 2012-10-25T17:31:06.233 に答える
2

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);
于 2012-11-06T08:45:30.537 に答える