Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share server from socket.io between files

I'm trying to be able to call io from other files. Point is that it doesn't update when a user is put into a room, or when io.sockets is called etc.

server.js

var options = {
  key: fs.readFileSync('./certs/file.key'),
  cert: fs.readFileSync('./certs/file.crt'),
  requestCert: false
};
var app = express();
var server = require('https').createServer(options, app);
var io = require('socket.io').listen(server); io.origins('*:*');
global.io = io;

io.on('connection', function(socket) {  .. }

I've also tried;

module.exports.io

and then from the other file

require('server.js').io

This didn't work either, I want to be running my server in one file which is the server js, I handle every incoming socket here etc. These are the two things I've tried but they both result in the same issue.

like image 609
VGO Exclusive Avatar asked Jul 20 '18 18:07

VGO Exclusive


1 Answers

There are many different schemes for sharing a central variable (like your io variable) with other modules. How exactly makes sense to do it depends upon an overall architecture, how you want your modules to be resuable, etc... but all use some combination of importing and exporting to share data between modules without using global.

In your specific case, you can do something very simple:

server.js

const options = {
  key: fs.readFileSync('./certs/file.key'),
  cert: fs.readFileSync('./certs/file.crt'),
  requestCert: false
};
const app = express();
const server = require('https').createServer(options, app);
const io = require('./socket.js').init(server);

io.on('connection', function(socket) {  .. }

socket.js

let io;
module.exports = {
    init: function(server) {
        // start socket.io server and cache io value
        io = require('socket.io').listen(server); io.origins('*:*');
        return io;
    }
    getio: function() {
        // return previously cached value
        if (!io) {
            throw new Error("must call .init(server) before you can call .getio()");
        }
        return io;
    }
}

In other modules that want access to io

const io = require('./socket.js').getio();

It should go without saying here that you have to call .init(server) before you can call .getio(). This takes advantage of the node.js module caching system so that each time you call require('./socket.js') it is returning to you the same module that was first loaded and thus you have access to the previously cached io instance.


FYI, this is called a "pull" model where a module that wants access to something else uses a require() statement to "pull" in the variable it wants.

There is also a push module where the loader of the module pushes the data to the module by calling a function in that module after it loads the module.


Here are some other ways to do it:

Export from app.js

You have to watch out for circular dependencies with this scheme because if app.js does require('./a.js') and then a.js does require('./app.js'), you can create a circular dependency which will fail. So, this model only works ifa.jsis doing arequire('./app.js')` after module load (like in a module constructor).

app.js

const options = {
  key: fs.readFileSync('./certs/file.key'),
  cert: fs.readFileSync('./certs/file.crt'),
  requestCert: false
};
const app = express();
const server = require('https').createServer(options, app);
const io = require('socket.io').listen(server); io.origins('*:*');


io.on('connection', function(socket) {  .. }

// exports some things we want to share
module.exports  = {
  io: io,
  app: app
};

some other files that wants access to io

 // module constructor
 modules.exports = function() {
     // can use io in here
     const io = require('./app.js').io;
}

Push Model

In this module, you pass the io variable to any other module that needs it when you load that other module.

app.js

const options = {
  key: fs.readFileSync('./certs/file.key'),
  cert: fs.readFileSync('./certs/file.crt'),
  requestCert: false
};
const app = express();
const server = require('https').createServer(options, app);
const io = require('socket.io').listen(server); io.origins('*:*');


io.on('connection', function(socket) {  .. }

// load someotherfile.js and pass it the io variable
require('./someotherfile.js')(io);

some other files that wants access to io

module.exports = function(io) {
    // put whatever code for your module here
    setInterval(function() {
        io.emit(...);
    }, 1000);
}
like image 115
jfriend00 Avatar answered Sep 17 '22 04:09

jfriend00