0

I have a node toplevel myapp variable that contains some key application state - loggers, db handlers and some other data. The modules downstream in directory hierarchy need access to these data. How can I set up a key/value system in node to do that?

A highly upticked and accepted answer in Express: How to pass app-instance to routes from a different file? suggests using, in a lower level module

//in routes/index.js
var app = require("../app");

But this injects a hard-coded knowledge of the directory structure and file names which should be a bigger no-no jimho. Is there some other method, like something native in JavaScript? Nor do I relish the idea of declaring variables without var.

What is the node way of making a value available to objects created in lower scopes? (I am very much new to node and all-things-node aren't yet obvious to me)

Thanks a lot.

Community
  • 1
  • 1
Dinesh
  • 4,437
  • 5
  • 40
  • 77
  • 1
    I used global (see http://nodejs.org/api/globals.html#globals_global) for this purpose, but I'm interested in any good alternatives. – user949300 Oct 29 '14 at 01:18

4 Answers4

1

This is not really related to node but rather general software architecture decisions.

When you have a client and a server module/packages/classes (call them whichever way you like) one way is to define routines on the server module that takes as arguments whichever state data your client keeps on the 'global' scope, completes its tasks and reports back to the client with results.

This way, it is perfectly decoupled and you have a strict control of what data goes where.

Hope this helps :)

Dmitry Matveev
  • 5,320
  • 1
  • 32
  • 43
  • You are right. But I was trying to avoid a signature like `func(handle, ...)` because then the handle has to be lugged around everywhere. – Dinesh Oct 29 '14 at 01:02
1

Since using node global (docs here) seems to be the solution that OP used, thought I'd add it as an official answer to collect my valuable points.

I strongly suggest that you namespace your variables, so something like

global.myApp.logger = { info here }
global.myApp.db = {
   url: 'mongodb://localhost:27017/test',
   connectOptions : {}
}

If you are in app.js and just want to allow access to it

global.myApp = this;

As always, use globals with care...

user949300
  • 15,364
  • 7
  • 35
  • 66
0

One way to do this is in an anonymous function - i.e. instead of returning an object with module.exports, return a function that returns an appropriate value.

So, let's say we want to pass var1 down to our two modules, ./module1.js and ./module2.js. This is how the module code would look:

module.exports = function(var1) {
    return {
        doSomething: function() { return var1; }
    };
}

Then, we can call it like so:

var downstream = require('./module1')('This is var1');

Giving you exactly what you want.

Brendan
  • 2,777
  • 1
  • 18
  • 33
  • That works, and so I am carrying on with my work thanks. But if I reorg my code so that now it is ./x/module1.js and ./module2.js then will I need to change any code? I am finding that I have to, but is there a workaround? – Dinesh Oct 29 '14 at 00:54
  • @Dinesh unless you want to *dynamically* load a module (i.e. you don't know where it is), you just have to change the string inside `require()`. If you want to dynamically find it, thats something different altogether. Don't forget to mark an answer as accepted :) – Brendan Oct 29 '14 at 01:14
  • .@Brendan I do. I iterate a particular directory, find files matching a certain pattern, instantiate the module, interrogate it for the types of HTTP requests they can handle, and configure one of two webservers. I was thinking of letting the modules load and register themselves against their respective capabilities. – Dinesh Oct 29 '14 at 02:40
  • @Dinesh maybe take a look at [node-glob](https://github.com/isaacs/node-glob), which may be your best bet. Otherwise, I'd advise against letting the application find the modules. – Brendan Oct 29 '14 at 06:06
  • @ Brendan yes, user949300 had recommended it and it's exactly what I needed. Thanks. – Dinesh Oct 29 '14 at 18:08
0

I just created an empty module and installed it under node_modules as appglobals.js

// index.js
module.exports = {};
// package.json too is barebones
{ "name": "appGlobals" }

And then strut it around as without fearing refactoring in future:

var g = require("appglobals");
g.foo = "bar";

I wish it came built in as setter/getter, but the flexibility has to be admired.

(Now I only need to figure out how to package it for production)

Dinesh
  • 4,437
  • 5
  • 40
  • 77
  • 1
    I also used something like this for a while but eventually changed to using http://nodejs.org/api/globals.html#globals_global `global` as it seemed slightly cleaner and simpler. – user949300 Oct 29 '14 at 01:19