NodeJS - Store Global variable - node.js

I'm currently trying to get a list of all of the members that are signed in. I'm using socket.js for this and using event handlers.
I have the following event:
eventEmitter.on('userSignedIn', function(socket, user) {
socket.emit("userJoined", {currentUsers: user.first_name});
});
Then, in JQuery, I am doing the following:
socket.on('userJoined', function (message) {
newItem = $("<li>Item " + message.currentUsers + "</li>").show();
$('.users-list').prepend(newItem);
});
This however is not working and not even showing the correct username(s).
Basically, what I want to do is when the event userSignedIn it appends an array users with the user that's just signed and then send this through the socket. But I'm struggling to see how I can store this inside the global app?

A global variable in node is accessed through process.env.
If you need to store this as a global variable in Node, go to the dotenv module, install it, (farily simple to use it) and use it to store your original global for the counter. In your .env file you would have say counter=1. Then you can increment it by accessing the global in your code by stating process.env.counter and you can increment it as well.
Remember: if you process stops running or goes down the counter will return to the original state of 1 when you bring it back up.
You can if you wish not use the dotenv module and simply create and access a process.env variable straight in your code. However, dotenv is very flexible, and you may want to use it for other purposes.
Hope this helps

Related

Is there any way to use global like values in a nodejs app?

I have this simple expressjs app that serve some data but this data are actualy less than 10 values so use a database seems like an overkill but to generete this values is a heavy process so what i have in mind is to run the process to generete the values when the app start and then serve this values in the app endpoints. Is there any way to keep this values consistenly without having to run the process of generarte the values from scratch?. I know that nodejs have a "global" values feature but i have reed that is not recommended to use it so i have been looking for an alternative any advise?
You can create a JSON file and add values to it, then require it and save it to a variable:
// example.json
{
"example": "I am an example!"
}
// server.js
const exampleData = require('./example.json');
console.log(exampleData.example) // Output: "I am an example!"

how to create environment variables to store data in a file?

Hey actually i am doing some project in Nodejs. I need a configuration file in order to store the data to file system but i do not know how to write a configuration file to store data to file. please help me with this. thanks in advance
Sounds to me that you are looking for the following NPM module/library - dotenv. You simply require('dotenv').config(); which is probably best placed at the top (after use strict;) and create a text file which would read as an example:
url_prefix='mongodb://'
url_ip='#localhost'
port=':27017/'
dbase='NameofDB'
Of course you can add anything you like to this file. Just remember it is a text file and should not contain spaces etc.
Though the default for the .env file is in the root of your project you can actually place it wherever you like, and simply put:
require('dotenv').config({path: '/custom/path/to/your/env/vars'});
(Above was taken from the dotenv documentation and it works as I use it in projects.)
To acquire any Global variable you would simply type:
process.env.url_prefix
Obviously from there you can build the needed entry code to your DB from process.env statements such as:
process.env.url_prefix+process.env.url_ip etc. OR
${process.env.url_prefix}${process.env.url_ip}
Using dotenv allows you to keep sane control over those process.env globals.
Be aware there is a gotcha! Be careful not to overwrite any of those globals in your code. As they will remain overwritten as long as your Node process is running.
If you mean you need some constants and business logic/data file to read from, you can simply include the file in your script using the require module.
Ex: Your file name is test.json, then:
var test = require('test.json');
Further, you can use a CONSTANT in the file as 'test.CONSTANT'
Note: Please make sure you use module.exports wherever needed. Details are here
Usually people use JSON to store configurations and stuff, since it is very javascripty.. You can simply make a JSON config file. In case you need to store some special data like SECRET URL, just use environment variables. FYI I found your question unclear. Does this answer your question.
const fs = require("fs");
// Example Config
let config = {
DB: "mongodb://blahblah:idhdiw#jsjsdi",
secret: "thisandthat",
someScript: "blah.js"
};
// Write to file.
fs.writeFile('config.cfg', JSON.stringify(config), err => {
if (err) throw err;
console.log("[+] Config file saved!");
// Retrieve
let confData = JSON.parse(fs.readFileSync('config.cfg'));
console.log(confData.secret);
});
// To save variables in environment variables
// Generally You will not set environment variables like this
// You will have access to setting environment variables incase
// you are using heroku or AWS from dash board. Incase of a machine
// you can use ** export SOME_ENV_VAR="value" ** in your bash profile
process.env.IP = "10.10.10.10";
// Too risky to put else where.
process.env.API_KEY = "2ke9u82hde82h8";
// Get Data
console.log(process.env.IP);
console.log(process.env.API_KEY);

Express4: Storing db instance

In express4, is it bad practice to store the db instance in app.locals or store it using app.set? Because I was thinking about it, since I will need it throughout my app it will be easier to access.
It should work just fine and no, I don't think it's bad practice (at least not horrible) - after all, app.locals is intended to provide you a safe place to put your global values.
However, using Express to store miscellaneous global values like this does result in your application being tightly bound to Express. If you ever decide that you want to remove Express and replace it with something else, you're going to have to hunt down and change all those references to app.local that are now scattered throughout your code.
If you want to avoid this, one simple pattern is to create a module exporting the value you want - this allows you to keep all the associated code in one place and import it whenever you need it. For example:
// modules/database.js
// initialize the database
const db = initializeDatabase();
// export a "getter" for the database instance
export const get = () => db;
Then, when you want to use the database instance:
// index.js
// import the database "getter"
import { get } from './modules/database';
// perform a query
const rows = get().query('SELECT * FROM table');
Just import modules/database anywhere you want to use the database.

Is it good practice to add database connection object to the process.env global in node.js?

We already use node's process.env Global Object to store/access environment variables but can we also attach other objects that need to be accessible across several files/modules ?
A concrete example:
Imagine you are connecting to a Datastore e.g. Redis1 and you are modularising your app so that each module would open its own connection to Redis.
Would it make sense to use the following:
process.env.redisClient = || process.env.redisClient || require('redis').createClient()
// use the shared/global connection for your needs:
process.env.redisClient.set('Hello', 'World');
process.env.redisClient.get('Hello', function(err, reply) {
console.log('Hello ' + reply);
});
I realise this question can be perceived as "subjective" or "opinion-based", but I'm not asking for anyone's opinion; I want to know if there are people with specific experience of cases where adding an object to process.env will "break production" or have another adverse effect.
1 its the same for any db where the number of connections should be minimised so applies to MySQL, PostgeSQL, MongoDB etc.
Sadly, this does not work.
We cannot attach an object or function to node's process.env Global object because all entries added to process.env are type-cast to String.
If you're interested in how we ended up solving this problem see: https://github.com/nelsonic/redis-connection

How to make my nodejs app serve multiple users?

I am implementing a very basic website using nodejs, and expressjs framework. The idea is that the user enters the website, click on a button that will trigger a cpu-intensive task in the server, and get a message on the browser upon the completion of the task.
The confusing part for me is how to accomplish this task for each user without blocking the event-loop, thus, no user has to wait for another to finish. Also, how to use a new instance of the used resources(objects, variables..) for each user.
After playing and reading around, I have come across child-process. Basically, I thought of forking a new child_process for each user so that whatever the time the sorting takes, it won't block my event-loop. However, I am still not sure if this is the best thing to do for such a scenario.
Now, I have done what I wanted to but with only single user, however when trying to start another user, things become messy and variables are shared. I know that I should not use global variables declared in the module, but what could be another way to make variables shared among functions within a single module yet they are different for each user!?
I know that the question may sound very basic, but I kinda miss the idea of how does node js serve different users with new variables, objects that are associated with each individual user.
In short, my questions are:
1- how does node serve multiple users simultaneously?
2- when and how should I resort to forking or executing a new child-process under the hood, and is it for each user or based on my # cores in cpu
3- how to separate resources in my application for each user such that each user has his own counters, emails and other objects and variables.
4- when do I need or I have to kill my child process.
Thanks in advance.
CODE:
var cp = require('child_process');
var child= cp.fork('./routes/mysort-module');
exports.user=function(req,res){
// child = new cp.fork('./routes/mysort-module'); // Should I make new child for each user?
child.on('message',function(m){ res.send('DONE');}
child.send('START PROCESS'); // Forking a cpu-intensive task in mysort-module.js
}
IN MY SORTING MODULE:
var variables = require(...);
//GLOBAL VARIABLES to be shared among different functions in this module
process.on('message',function(m){
//sort cpu-intensive task
process.send('DONE');
});
// OTHER FUNCTIONS in THE MODULE that make use of global variables.
You should try to split up your question. However, I hope this answers it.
Question 1: A global variable is not limited to request scope. That's a part of Node's definition for a global and it doesn't make sense to enforce this somehow. You shouldn't use globals at all.
The request scope is given by the HTTP module:
http.createServer(function(req, res) {
var a = 1;
// req, res, and a are in request scope for your user-associated response
});
Eliminating globals shouldn't be that hard: If module A and B share a global G and module C calls A.doThis() and B.doThat(), change C to call A.doThis(G) and B.doThat(G) instead. Do this for all occurrences of G and reduce its scope to local or request.
Additionally, have a look for "Sessions", if you need a scope coverig multiple requests from one client.
Question 2: Start the child process inside the request handler:
exports.user = function(req,res){
child = new cp.fork('./routes/mysort-module');
Question 3: See question 1?
Question 4: After the process returned the calculated results.
process.on('DONE', function(result) {
process.exit();
// go on and send result to the client somehow...
});

Resources