I checked this How do I define global variables in CoffeeScript?
for declaring a global variable i.e., declaring in the app.js and accessing in the routes/index.coffee
I declared (exports ? this).db = redis.createClient() in the app.coffee and tried to access the db in the routes.index.coffee using db.set('online',Date.now(), (err,reply) -> console.log(reply.toString()) ) this doesn't seem to work...what is happening..I am on node 0.8.9
There are other approaches in which it works but curious to know what is happening...
Also tried the #db = redis.createClient() in the app.coffee which doesn't work either
Thanks
exports doesn't define "globals;" it defines "public" members of a module available via require. Also, exports is always initially defined and exports === this, so (exports ? this) isn't actually doing anything.
However, since globals are generally frowned upon (and do defeat some of the intents of Node's module system), a common approach for web applications is to define a custom middleware allowing access to the db as a property of the req or res objects:
# app.coffee
app.use (req, res, next) ->
req.db = redis.createClient()
next()
# routes/index.coffee
exports.index = (req, res) ->
req.db.set('online', Date.now(), (err,reply) -> console.log(reply))
An example of this can be found in decorate.js of npm-www, the repository behind npmjs.org:
function decorate (req, res, config) {
//...
req.model = res.model = new MC
// ...
req.cookies = res.cookies = new Cookies(req, res, config.keys)
req.session = res.session = new RedSess(req, res)
// ...
req.couch = CouchLogin(config.registryCouch).decorate(req, res)
// ...
}
Though, if you'd still rather define db as a global instead, Node.JS defines a global variable you can attach to:
global.db = redis.createClient()
Related
Hi,
I have a node server. This is what my init file looks like:
require("variables");
require("constants");
require("index");
app.get('/', function (req, res, next) {
res.sendFile(__dirname + '/index.html');
});
httpServer.listen(port, () => {
console.log(`server running`);
});
My variables file looks like this:
file = "file.json";
dataopen = "stuff";
userdata = "user";
module.exports={file,dataopen,userdata}
whereas my constants file:
const button = "<div></div>";
const title = "Page Title";
const input = "submit";
module.exports={button,title,input}
The thing here is that if I call for a variable inside index.js it will read it just fine:
console.log(dataopen); //it will output 'stuff'
but not so with any constants which will output undefined unless I include this line on top:
const { button,title,input } = require("constants");
why is that? Why do I need the extra line for constants but not for variables as well? I also noticed that by removing the prefix const before declaring then I wont need the line but why is that?
Thank you.
Do a console.log(global). Chance are that you will see your dataopen and the other vars.
In a nutshell, by not "declaring" a variable, it will implicitly be global. And when you try to access an undeclared variable, js regards it is a global variable. Something that is not allowed anymore in strict mode.
Should not be said, but global vars bad, do not use them.
My log.js,
var data ;
var winston = require('winston');
var config = {'status':1};
module.exports.config = config;
My get.js file(from where i want to modify log.js),
exports.getcategories = function (req, res) {
if(log.status == 1){
var data = 'loaded successfully';
}
};
Here i want to modify my data variable in log.js from my get.js,can anyone please suggest help.
You need to read up on Javascript scopes. In order to access any variable in a file or function from outside it, there are only two ways:
Make the variable global (NOT a good idea).
Create getter/setter functions and export them, thereby exposing it to the outside world
When i am doing nested express apps, nested app use does not work
var app = express();
var localApp = express();
app.use('/pdf-exporter', PDFExporterModule());
function PDFExporterModule(app) {
localApp.use(function(req, res, next) {
//this code never execute !!!!!!
next();
});
localApp.get('/subpath/:userId', function() {...});
return localApp;
}
localApp doesn't have a value when you first call PDFExporterModule(). Move var localApp=express() up, or better yet, don't define local app outside of PDFExporterModule.
Also, it's good practice to leave all your var statements at the top. Variable hoisting makes localApp exists and is undefined right at the top of your script. It gets its value though where you have var localApp=express() below.
I'm using Express and Passport for node.js to build a simple web server, I coded a simple module and then I loaded the module inside a GET request, everything works great until more than one user access the request.
I use to believe that a "var" inside an "app.get" function was removed from memory after the function finished, but isn't the case, I use some local variables inside the external module and the values are being shared between users, the module looks like this:
var some_value=0;
function some_method(){
some_value++;
return some_value;
}
exports.some_method = some_method;
And the Express request code looks like this:
app.get('/someurl', function(req, res) {
var some_extermal_module = require('/some_extermal_module'); // <-----Right way?
var data = some_extermal_module.some_method();
res.render('view', {
title : 'Title',
data_to_vew: data
});
});
An object inside a "app.get" request stays always in memory regardless of is being accessed by a different user?
How to clean a "var" object after it runs?
How can I avoid this memory conflicts?
Do I have to code differently the module or call differently the module?
Thanks a lot.
UPDATE: I guess this is a proper solution but I need the review of some node.js/Express expert for approval it or correction.
app.js:
var ext_mod = require('./module');
var express = require('express');
var app = express();
app.get('/', function(req, res){
var ex_mod_instance = new ext_mod({});
ex_mod_instance.func_a({},function(ret){
res.send('Hello World: '+ret);
});
ex_mod_instance = null; // clean
});
app.listen(8080);
console.log('Listening on port 8080');
module.js:
var node_module = function(config) {
this.config = config;
this.counter=0;
};
node_module.prototype = {
func_a: function(param,done) {
this.counter++;
done(this.counter);
},
func_b: function(param,done) {
}
};
module.exports = node_module;
Is this the best way to save memory (leaks)?
Every time a function is called you do get "clean" local variables in the local scope. Modules are for the purpose of writing clean, organized code, so that you do not have every function and variable in the global scope. I believe require does cache the module, so maybe you are having a problem with variables in the closure around the function exported from the module. You'll have to include more code.
One way you could solve this is by exporting a function that creates the module. That function could be your constructor, which will scope your counter locally.
Again, this is one solution.
Your variable 'some_value' is global in the context of the module. So each time a request use this module, it uses the same variable.
(Require does cache the modules wich are loaded only the first time)
I can think of 2 ways to achieve this:
either you want one variable per request, and you declare this variable in the module function, or in the res.locals.some_value if you want to use it in many functions during the same request
either you want one variable per user, and then you need to use express session middleware, and add the variable to req.session.some_value
For example I want to use custom logger:
logger = require('basic-logger'),
logger.setLevel('info')
var customConfig = {
showMillis: true,
showTimestamp: true
}
var log = new logger(customConfig)
How to use this logger in other modules instead of console.log ?
Most people advise against using global variables. If you want the same logger class in different modules you can do this
logger.js
module.exports = new logger(customConfig);
foobar.js
var logger = require('./logger');
logger('barfoo');
If you do want a global variable you can do:
global.logger = new logger(customConfig);
global.myNumber; //Delclaration of the global variable - undefined
global.myNumber = 5; //Global variable initialized to value 5.
var myNumberSquared = global.myNumber * global.myNumber; //Using the global variable.
Node.js is different from client Side JavaScript when it comes to global variables. Just because you use the word var at the top of your Node.js script does not mean the variable will be accessible by all objects you require such as your 'basic-logger' .
To make something global just put the word global and a dot in front of the variable's name. So if I want company_id to be global I call it global.company_id. But be careful, global.company_id and company_id are the same thing so don't name global variable the same thing as any other variable in any other script - any other script that will be running on your server or any other place within the same code.
you can define it with using global or GLOBAL, nodejs supports both.
for e.g
global.underscore = require("underscore");
or
GLOBAL.underscore = require("underscore");
I would suggest everytime when using global check if the variable is already define by simply check
if (!global.logger){
global.logger = require('my_logger');
}
I've found it to have better performance
Global variables can be used in Node when used wisely.
Declaration of global variables in Node:
a = 10;
GLOBAL.a = 10;
global.a = 10;
All of the above commands the same actions with different syntaxes.
Use global variables when they are not about to be changed
Here an example of something that can happen when using global variables:
// app.js
a = 10; // no var or let or const means global
// users.js
app.get("/users", (req, res, next) => {
res.send(a); // 10;
});
// permissions.js
app.get("/permissions", (req, res, next) => {
a = 11; // notice that there is no previous declaration of a in the permissions.js, means we looking for the global instance of a.
res.send(a); // 11;
});
Explained:
Run users route first and receive 10;
Then run permissions route and receive 11;
Then run again the users route and receive 11 as well instead of 10;
Global variables can be overtaken!
Now think about using express and assignin res object as global.. And you end up with async error become corrupt and server is shuts down.
When to use global vars?
As I said - when var is not about to be changed.
Anyways it's more recommended that you will be using the process.env object from the config file.
If your app is written in TypeScript, try
(global as any).logger = // ...
or
Object.assign(global, { logger: // ... })
However, I will do it only when React Native's __DEV__ in testing environment.
May be following is better to avoid the if statement:
global.logger || (global.logger = require('my_logger'));