how to use global variable(sharable variables) in Node.js&Express - javascript

I have a file called data.js for keeping data as memory database.
var express = require('express');
var app = express();
var aList;
var bList;
var cList;
module.exports = app;
And I want to initialise data when I start the server. So, I implemented init() in app.js
...
var data = require('./data'); // data.js is located in the same folder.
app.set(...);
app.use(...);
...
init();
...
});
fun init(){
console.log("Hello!");
aList = getDumpDataList(10); // I also tried with 'data.aList = getDumpDataList(10);' but didn't work.
console.log(JSON.stringify(aList));
}
fun getDumpDataList(n){
var list;
... // for loop to generate random elements.
return list;
}
module.exports = app;
When I printed with console.log(), Hello! is printed but aList isn't printed but undefined
And I also want to use the data in routers under routes folder.
So, what I did is.
...
var data = require('./data');
route.get("/...", function(req, res, next){
console.log(JSON.stringify(aList));
...
});
But it is also undefined.
I am just making simple test server that initialise data whenever I re-run.
How can I share variables between the js files?

You do not export those vars:
const express = require('express');
const app = express();
let aList;
let bList;
let cList;
module.exports.app = app;
module.exports.aList = aList;
module.exports.bList = bList;
module.exports.cList = cList;
...but i would not put express in data.js, rather put it in app.js.
I would also initialize those vars with initial values in data.js, if the initial data does not depend on something else.
Last but not least: Do not use var anymore, use let and const instead. It is supported since Node 6+ (https://node.green/). I replaced it in the code.

Related

expressJS require a file which has route object from two different place does not work

I am working on an expressJS project. I have a route file named send_email.js, and I want to use parts of this file from two different places. These places are index.js and user.js.
So I added the following line for both of index.js and users.js:
const send_email = require("./send_mail");
But user.js is giving me an error because send_email is undefined. And then I just delete the same line from index.js and everything goes fine. I can reach send_mail in user.js, and it is what I expect.
Am I overlooking something about requiring files in expressJS? I can use this technique effectively in other projects. Are there expressJS specific things which cause this error?
I created same situation in another tiny project and its' codes like these:
// ------------------------index.js -----------------------
const express = require("express");
const app = express();
/* if coment this two line every thing goes fine */
const mylog = require("./deneme1").mylog;
mylog();
/* if coment this two line every thing goes fine */
const yourlog = require("./deneme2").yourlog;
const route = require("./deneme1").route;
console.log('route :', route);
yourlog();
app.get("/", (req, res)=>{
res.send("OK!");
})
app.listen(3000, () => { "listening on "+3000});
// --------------deneme1.js -------------------------
const express = require("express");
const route = express.Router();
const yourlog = require("./deneme2").yourlog;
console.log('yourlog mmm:', yourlog);
route.get("/deneme", function(req, res){
mylog();
res.send("OK!");
});
function mylog () {
console.log("mylog in deneme1.js");
};
module.exports.route = route;
module.exports.mylog = mylog;
// ------------------deneme2.js-----------------
const express = require("express");
const route = express.Router();
const mylog = require("./deneme1").mylog;
console.log('mylogxx :', mylog);
function yourlog(){
console.log("yourlog deneme2");
mylog();
console.log("----");
}
module.exports.yourlog = yourlog;
deneme1.js and deneme2.js require each other and express.js require both of deneme1.js and deneme2.js.
Did you export in your send_mail.js file? You should export whatever function you want to reuse . And use import wherever you need it. Instead of require.
For reference :MDN
I have realized that my problem is related "cyclic dependencies" between my route files. It is kind of design mistake. And there is a stackoverflow question/solution about it:
how-to-deal-with-cyclic-dependencies-in-node-js

loopback model access in custom js file

i want to access a model name userRegistration in my custom js file but every time its showing undefined and shows this error
TypeError: Cannot call method 'findOne' of undefined
please Check code
var loopback = require('loopback');
var app = loopback();
var nodemailer = require("nodemailer");
var smtpTransport = require("nodemailer-smtp-transport");
var path=require('path');
var fs=require('fs');
var Handlebars = require('handlebars');
exports.mailToUser=function(req,res,next){
var userNotification = app.models.UserNotification;
var userregister = app.models.UserRegistration;
userregister.findOne({where:{email:email}},function(err,userobj){
if(err){
next()
}
})
}
Thanks
You shouldn't use var app = loopback();
If you want to access to app you can require your server.js or some other ways existed. The simple one is requiring server

How to create a reusable Socket.IO module

I have troubles for creating a module which exposes functionalities for my Socket.IO library:
const sio = require('socket.io');
module.exports = function(server) {
const io = sio(server);
return {
register: function(namespace) {
let nsp = io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
The problem is now how do I make use of this in other modules? In my app.js
I create the server with Express and can instantiate the module with require('./mysocketio')(server) but not in other modules because server is not available there. What's a nice way to resolve these circular dependencies?
Well you can achieve those in various ways, like:
setting objects to global namespace. (altering global needs care)
Use module.exports and require the object in the other files. (can lead to circular dependency issues if not done properly)
pass the instance as arguments to the controllers, while requiring them in routes.
myModule.js Module which exposes functionalities of your Socket.IO library
const sio = require('socket.io');
module.exports = function(server) {
const io = sio(server);
return {
register: function(namespace) {
let nsp = io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
FLow 1: set the module in global namespace.
app.js
var app = require('express').createServer();
var io = require('./myModule')(app);
global._io = io;
app.listen(80)
controller.js
module.exports = function(io){
var that={};
/*
* Private local variable
* made const so that
* one does not alter it by mistake
* later on.
*/
const _io = global._io;
that.myAction = function(req,res){
_io.register('newRoom');
res.send('Done');
}
return that;
}
Flow 2: passing module as arguments.
app.js
var app = require('express').createServer();
var io = require('./myModule')(app);
require(./router.js)(app,io);
app.listen(80);
router.js
/*
* Contains the routing logic
*/
module.exports = function (app,io) {
//passing while creating the instance of controller for the first time.
var controller = require("./controller")(io);
app.get('/test/about',controller.myAction);
};
controller.js
module.exports = function(io){
var that={};
const _io = io;
that.myAction = function(req,res){
_io.register('newsRoom');
res.send('Done');
}
// everything attached to that will be exposed
// more like making public member functions and properties.
return that;
}
Flow 3: Setting io to global. Thus no need to pass server every time.
app.js
var app = require('express').createServer();
require('./myModule')(app);
require(./router.js)(app);
app.listen(80);
controller.js
// no need to pass the server as io is already initialized
const _io = require('./myModule')();
module.exports = function(io){
var that={};
that.myAction = function(req,res){
_io.register('newsRoom');
res.send('Done');
}
return that;
}
myModule.js
module.exports = function( server ) {
const _io = global._io || require('socket.io')(server);
if(global._io === undefined){
//initializing io for future use
global._io = _io;
}
return {
register: function(namespace) {
let nsp = _io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
Probably, the cleanest way is to pass is as arguments to the controllers, while requiring them in routes. Although 3rd flow seems promising but one should be care full while altering the global namespace.
It's not really a circular dependency; It's just that your module a) depends on another module that's not globally available and b) your module is presumably used in many places in your code.
Global
A possible solution (with downsides), is to just load your module once, and attach it to a global:
global.mysocketio = require('./mysocketio')(server);
This allows you to access global.mysocketio anywhere in your project, once it has been loaded. This is a construction that I personally use for an own logger construction; My logger is used in many places around my code, so I just keep it attached to global.log.
However, usage of globals is a bit dirty; It gives problems with namespace-separation (what is somewhere some code decides to use global.mysocketio itself), and it creates an 'invisible' dependency; Other code just assumes that a certain global will exist, and it's not that easy to find these dependencies.
Export
A nicer solution is to just pass the variable wherever needed. There are many ways to do this. I understand that your app.js doesn't have the server variable available, but it surely is including your express-code in some way. If you need the 'server' or 'mysocketio' available from app.js, just export it from your module where you are creating 'server'. Like:
module.exports.expressServerVar = server;
Just my 2 cents; Do you strongly disagree with me or am I missing something important? Let me know!
I'd use a factory or dependency injection. You could use something like jimple.
But here's an example without using any external dependencies. This is by no means the best code example but it should hopefully get the point across. I'd still recommend using jimple rather than this.
// app.js
var express = require('express');
var app = express();
var factory = require('./factory.js');
factory.setExpress(app); // This could also be done in the factory constructor. Or you could instanciate your express app in the factory.js class.
// factory.js
var socketIoModule = require('./your-socket-io-module.js')
function Factory() {
}
Factory.prototype.setExpress = function(app) {
this.app = app;
}
Factory.prototype.getSocketIOModule = function() {
return socketIoModule(this.app);
}
// By exporting it this way we are making it a singleton
// This means that each module that requires this file will
// get the same instance of factory.
module.exports = new Factory();
// some code that needs socket io module
var factory = require('./factory.js');
function() {
var socketIo = factory.getSocketIOModule();
socketIo.doStuff();
}
Approach that I use in my applications is exposing server and io instances from start script and reusing them in modules
// Setup servers.
var http = require('http').Server(app);
var io = require('socket.io')(http);
// Setup application.
require('./server/app')(app, express, io);
// Start listening on port.
http.listen(configs.PORT, function() {
console.log("Listening on " + configs.PORT);
});
Inside your modules you can use io instance to setup event handlers or emit events, something like this
module.exports = {
contest: function(io, contest) {
var namespace = io.of('/' + contest.id);
namespace.on('connection', function(socket) {
socket.on('word', function(data) {
...
});
});
}
};
For your sample
I would put this part in app.js or in js file that is used to start server
const sio = require('socket.io');
const io = sio(server);
and will have Socket.IO module like this
module.exports = function(server, io) {
return {
register: function(namespace) {
let nsp = io.of(namespace);
nsp.on('connect', function(socket) {
// ...
}
}
}
}
My sample
https://github.com/gevorg/typeitquick/blob/master/web.js
https://github.com/gevorg/typeitquick/blob/master/server/contest.coffee
https://github.com/gevorg/typeitquick/blob/master/server/io.coffee

How to access variables declared in main app.js in separate route files in node.js Express 2.5.5?

I just started using a new version of Express (2.5.5) that by default creates a ./routes directory along with ./views and ./public
Inside of routes there is a index.js file which contains:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Express' })
};
by default (after running express from the commandline) and this is the routes section in the main app.js:
// Routes
app.get('/', routes.index);
I've set up a variable for a redis client in the main app.js:
var redis = require('redis'),
db = redis.createClient();
and I was wondering how I could access the methods of db (and whatever other modules I require in app.js) in the files contained in ./routes
I really liked Jamund's solution, but I would extend the concept to this:
// db.js
var redis = require('redis');
module.exports = redis.createClient();
// index.js
var db = require(.'/db')
// whatever other file
var db = require(.'/db')
// do something with db
db.disconnect();
both db on index and other file would get the same instance of the redis client
Just call this at the top of your files. Requires are in a shared space, so you can re-require the file multiple times and it will always reference the same version. If you want to be fancy you can create your own db module that does something like this, to prevent double creating clients:
// db.js
var db
var redis = require('redis')
exports.connect = function() {
if (!db) db = redis.createClient()
return db
}
exports.disconnect = function() {
redis.quit()
db = null
}
// index.js
var dbHelper = require(.'/db')
var db = dbHelper.connect()
// whatever other file
var dbHelper = require(.'/db')
var db = dbHelper.connect() // won't connect twice
You can either create an app global and hang the vars you want to share off that or you can use an initializer function in your routes file
f.e.
// app.js
var app = express.createServer()
, db = require('redis').createClient();
require('./routes').with(app, db);
// routes.js
module.exports.with = function(app, db) {
app.get('/',function(r,s) { s.end('Sweet');});
}

Accessing globals from node.js modules?

I want to separate some functions into a file named helpers.js, in which I have put the below shown code. What should I do to access the app variable from inside my method in order to be able to fetch my config element named Path?
Helpers = {
fs: require('fs'),
loadFileAsString: function(file) {
return this.fs.readFileSync( app.set('Path') + file)+ '';
}
}
module.exports = Helpers;
So from what I see you need the app variable form Express. You can send it as a function param to loadFileAsString, for ex:
helpers.js
Helpers = {
...
loadFileAsString: function(file, app) {
return this.fs.readFileSync( app.set('Path') + file)+ '';
}
}
module.exports = Helpers;
some_file.js
app = express.createServer();
...
helpers = require('./helpers.js');
helpers.loadfileAsString(file, app);
If you want the app to be global though you can do that also: global.app = app and you can access app everywhere without sending it as a function param.

Categories