Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing socket.io to other modules gives empty object

I am trying to share socket.io's socket object in different node.js modules although I fail and get empty object with

Cannot call method 'on' of undefined

My code :

app.js

var express = require('express')
  , app = express();

var server = require('http').createServer(app)
  , io = require('socket.io').listen(server)

var routes = require('./routes')
  , path = require('path')
  , rss = require('./routes/rss')

// ...

exports.io = io;

routes/rss.js

io = require(__dirname + '/../app');

console.log(io);
io.sockets.on('connection', function(
  console.log("Connection on socket.io on socket");
  // .. do stuff 
});

That's the output I get from this :

$ node app.js                                                                                                    
   info  - socket.io started
{}

/home/XXX/programming/nodejs/node-express-aws/routes/rss.js:10
io.sockets.on('connection', function(socket){
           ^
TypeError: Cannot call method 'on' of undefined
    at Object.<anonymous> (/home/XXX/programming/nodejs/node-express-aws/routes/rss.js:10:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/home/XXX/programming/nodejs/node-express-aws/app.js:9:10)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)

Although I have tried and I can do the same with socket.io only in one (app.js) file

var express = require('express')
  , app = express();

var server = require('http').createServer(app)
  , io = require('socket.io').listen(server)

var routes = require('./routes')
  , path = require('path')
  , rss = require('./routes/rss')

// ...

io.sockets.on('connection', function(socket){
  logger.debug("Connection on socket.io on socket");
  socket.emit('news', {will: 'be recived'});
});
like image 913
Patryk Avatar asked Dec 09 '13 01:12

Patryk


2 Answers

Since, in app.js, you have:

exports.io = io;

then you would need to use it like so:

var app = require('../app');
var io = app.io;

That is you say, you attached a property called io to the module, so when you require that module, you get an object that has the io property set.

You could also do

module.exports = io;

and then leave rss.js as you have it now.


All that said, if you're running app.js with Node, you'll much more commonly see the io object injected into other modules (instead of the other way around); for example:

app.js

var express = require('express')
  , app = express();

var server = require('http').createServer(app)
  , io = require('socket.io').listen(server)

var routes = require('./routes')
  , path = require('path')
  , rss = require('./routes/rss')

// ...

rss(io); // pass `io` into the `routes` module,
         // which we define later to be a function
         // that accepts a Socket.IO object

routes/rss.js

module.exports = function(io) {
  io.sockets.on('connection', function(
    console.log("Connection on socket.io on socket");
    // .. do stuff 
  });
}
like image 122
Michelle Tilley Avatar answered Sep 19 '22 16:09

Michelle Tilley


I pass the io object into the connection handler.

var socket = require('./routes/socket.js');

io.sockets.on('connection', function(sock){
    socket.stuff(sock, io);
});

./routes/socket.js should contain the following:

var socket = module.exports = {};

socket.stuff = function(sock, io){
    //handle all events here
};
like image 23
chovy Avatar answered Sep 19 '22 16:09

chovy