1

In my chat application using nodejs and socket.io, I need to share variable across different modules such that the value modified on one file should be accessed from other file. A workflow of my app is as follows.

In main app.js I have included a controller file for authenticating "users.js" In which I use a variable say for example var onlineusers ={}; On each login, the value is inserted into this variable. For handling socket chat, I used another controller file named chat.js where I need to use the same variable onlineusers.

Now Consider 3 files app.js,user.js,chat.js

In app.js
var users = require('./users.js');
var chat = require('./chat.js');
users.set(app);
chat.set(app,io);


In user.js

module.exports.set = function(app) {
// var onlineusers  modified in some function
}

In chat.js

module.exports.set = function(app,io) {
// var onlineusers  modified in some function
}

What i need is sharing the variable var onlineusers value across different modules(user.js and chat.js)

Ajith
  • 2,476
  • 2
  • 17
  • 38
  • Store the variable in one module and export a method that retrieves the value. You can then get the value of the same variable from either module. – jfriend00 Jan 09 '17 at 07:01
  • One more query, Does it affect the performance if the number of online users increases. Also I need to use variables for rooms as well – Ajith Jan 09 '17 at 08:19
  • No, this doesn't affect the performance as online users increase in any way. There's one module instance loaded in your server period. You're just creating an accessor function to get at some data stored in the module. That's a common and good way to share data that has no scalability downsides. – jfriend00 Jan 09 '17 at 08:25

1 Answers1

2

What I would do is change chat.js and user.js .set functions to accept another paramter called onlineUsers. Then from app.js you can pass an onlineUsers value to each modifying .set functions.

// In app.js
var users = require('./users.js');
var chat = require('./chat.js');
var onlineUsers = new require('./onlineUsers')();
users.set(app, onlineUsers);
chat.set(app,io, onlineUsers);

// In user.js
module.exports.set = function(app, onlineUsers) {
  // onlineusers modified in some function
};

// In chat.js
module.exports.set = function(app, io, onlineUsers) {
  // onlineusers modified in some function
};

// In onlineUsers.js
module.exports = function(params) {
  // constructor for onlineUsers data model
};

This works because JavaScript passes by value.

'use strict';
let obj = {};
(function firstModifier(obj) { 
  obj.first = true;
})(obj);
console.log(obj);

This will only work to an extent. I would strongly consider using a database for this type of work. For managing online users with node & socket.io, I've found mongodb and redis to both be really good choices. The worthwhile benefit of this is your onlineUsers collection is databased instead of using an onlineUsers variable in application memory. Then your application can just access the db instead of "sharing" a variable.

theoretisch
  • 1,718
  • 5
  • 24
  • 34
  • Thanks for your answer. One question what you think about using global variable in seperate file "onlineUsers.js" like you mentioned above instead of database. If we use database, it can cause some delay on execution at different updation and fetching also concurrency issues?. So I am planing to use variable, but I am anxious about why you said that "Variable will work to an extend" – Ajith Jan 09 '17 at 08:00
  • It will work to an extent in that you are limited to application memory. This could very well be more than fine for your use. If you have a lot of online users and are storing sizable amounts of data on each of those users (i.e. an array of big objects), then one instance of a node process might not do the job. See http://stackoverflow.com/questions/7193959/memory-limit-in-node-js-and-chrome-v8. I think using onlineUsers.js as above or using @jfriend00's approach is perfectly fine if you don't expect to manage that many users. – QuasiFigures Jan 09 '17 at 08:22
  • I will add that by having online users data stored in a variable inside of one node process you'll lose all that data when that process dies. So if this is for a learning experience or small project its tots cool - but you couldn't do something like this with a user base and expect good results. – QuasiFigures Jan 09 '17 at 08:30
  • @Ajith in addition to what Yod says, overhead for something like Redis can be as little as few milliseconds, if your Redis node is close. E.g. on AWS, latency from Node apps to Redis is 1-2ms. Add some management overhead and it's still probably under 5ms. So you shouldn't be afraid of that. – Zlatko Jan 09 '17 at 11:06
  • Another point is that if you're afraid that your load will hit concurrency and delays, you're probably even more likely your in-memory will get stuck. – Zlatko Jan 09 '17 at 11:08
  • I have started my application with mongodb database and use an object variable to store online users and rooms, What is your opinion about it, considering maximum users wont exceeds more than 200. – Ajith Jan 10 '17 at 05:00
  • Glad you decided on a db. It's the only way to go really. Mongo is a great choice. Your application code - the .set functions in particular - should save to the database and I'm sure you'll need functions that read from the database. For interacting with the db in code, I would highly suggest using the npm mongoose as it's the industry standard ODM for mongo. – QuasiFigures Jan 10 '17 at 08:40