Michael Joseph Aubry
Michael Joseph Aubry

Reputation: 13422

Socket.io with multiple namespaces?

I have a route that listens to a particular route id.

/**
 * Chat app routes.
 */
app.get('/games/:id', gameChatController.chatRoom);

Based on the route id I can determine what game the chat is about.

My question is how do I use this to pass into socket.io?

bin/www

/*
* setup socket.io, and socket-session
*/
var socketIO = require('socket.io');
var io = socketIO(server);
var SessionSocket = require('session.socket.io');
var sessionSockets = new SessionSocket(io, app.sessionStore, app.cookieParser);
var setEvents = require('../events');
setEvents(sessionSockets);

events/index.js

'use strict';
var redis = require('redis');
var sub = redis.createClient();
var pub = redis.createClient();
sub.subscribe('chat');

module.exports = function(io) {

    // here io basically is sessionSockets

    // TODO: Set a namespace, make it dynamic
    var theRoom = 'fifa14';
    var namespaceRoom = io.of('/'+theRoom);

    namespaceRoom.on('connection', function(err, socket, session) {
        if (!session.user) return;

        console.log(socket);

    }
}

So what I am asking is how can I build this so that I can easily pass the current state of the app to match the state of the socket namespace, so users inside a particular game can only chat inside that?

Because I dont think doing something like the below is very efficient

controllers/chat.js

/**
 * GET /
 * ChatRoom page.
 */
exports.chatRoom = function(req, res) {

/*
* setup socket.io, and socket-session
*/
var socketIO = require('socket.io');
var io = socketIO(server);
var SessionSocket = require('session.socket.io');
var sessionSockets = new SessionSocket(io, app.sessionStore, app.cookieParser);
var setEvents = require('../events');
// so here I can pass the route parameters, not efficient!
setEvents(sessionSockets, req.params.id);

  res.render('chatRoom', {
    roomName: req.params.id
  });
};

So now I can pass a new game id into the setEvents(), but I think this can be better.

'use strict';
var redis = require('redis');
var sub = redis.createClient();
var pub = redis.createClient();
sub.subscribe('chat');

module.exports = function(io, gameId) {

    // here io basically is sessionSockets

    // Now I can pass the proper id
    var namespaceRoom = io.of('/'+gameId);

    namespaceRoom.on('connection', function(err, socket, session) {
        if (!session.user) return;

        console.log(socket);

    }
}

Upvotes: 3

Views: 3465

Answers (1)

jfriend00
jfriend00

Reputation: 707318

It's hard to tell exactly what question you're asking here so I'll explain conceptually how this can work.

Your chat app route is per client. Each client separately hits that route. If you want to share some state with a future incoming socket.io connection from that same client, you have two main ways of doing so:

  1. When the route is hit, you can set a cookie and put the particular state in the cookie. Then, when an incoming socket.io connection arrives, you can check the cookie to see which chat room this socket should go to.

  2. When the route is hit, you can set a session ID (as a cookie) and then store some state in some sort of session store. Then, when an incoming socket.io connection arrives from that client, you fetch the session ID from the cookie and you can then look into the session store to see what state goes with this socket.io connection.

You can't pass anything directly to socket.io because both incoming http routes and incoming socket.io connections are per client and are not at the same time so you can't set any global state about a particular future socket.io connection. Instead, you use the client cookie to either set some state on that particular client or to establish a session ID so the state can be in your session store.

Upvotes: 4

Related Questions