Search code examples
node.jssocket.ioexpress-4express-generator

Node.js Express 4 Generator with Mutliple Socket.io files


I broke my app into modules to add to it in the future. I'm using express 4 with the generator and running into issues with adding my multiple socket.io listeners.

In /bin/www

app.io.attach(server);

In app.js

var app = express();

//call socket.io to the app for each route
app.io = require('./socket.io/file1');
app.io = require('./socket.io/file2');
app.io = require('./socket.io/file3');

Everything worked great until I try to add more than one socket.io source file. Then only the last one works. I assume because app.io gets reset each time I call it.

What's the best way to go about this? I want to keep my code broke up as much as possible.


Solution

  • You're overwriting app.io each time. app.io = require('./socket.io/file1'); isn't "calling socket.io" but assigns app.io to that module. There are multiple ways to solve this, for example:

    in app.js:

    app.io = [
        require('./socket.io/file1'),
        require('./socket.io/file2'),
        require('./socket.io/file3')
    ]
    

    in /bin/www:

    app.io.forEach(function (socketIo) {
        socketIo.attach(server);
    });
    

    This assigns an array to app.io and /bin/www iterates over the array to attach the server to each socket.io instance.

    I couldn't test if this works and i suspect it doesn't (I wrote it just to illustrate the first problem in your code). I think one can use only a single socket.io instance per http server. But there is a solution:

    tl;dr

    Use socket.io namespaces. Create a single instance of socket.io and attach it to the server like you already do, then create "submodules" via io.of("/module-name") in each of your module files (like file1, etc). Please read the documentation to learn more about namespaces.


    Update:

    There are again multiple options to do that, e.g.: (Warning, code is from one of my own codebases, and is originally written in coffee-script and translated in my head, but you should get the gist)

    in io.coffee

    var io = require('socket.io')(http)
    
    require('./broadcast.coffee')(io)
    require('./livelog.coffee')(io)
    

    Where http is, of course, your http server instance.

    in broadcast.coffee

    module.exports = function (io) {
        var broadcast = io.of('/broadcast')
    
        broadcast.on('connection', function (socket) {
            socket.emit('foo', 'bar')
        })
    }