简体   繁体   中英

Method for dealing with variable scope in Node.js

I'm building a web server in Node.js from scratch (No express, no mongoose). My code (much simplified) looks something like this:

var app = {};

app.config = require('./config');
app.http = require('http');
app.router = require('./router');
app.mongoDb = require('mongodb');
app.mongoClient = app.mongoDb.MongoClient;
app.mongoClient.connect(
        'mongodb://'
        + app.config.db.server + ':'
        + app.config.db.port + '/'
        + app.config.db.catalog, function(err, db) {
if (!err) {
        app.db = db;
        app.httpServer = app.http.createServer();
        app.httpServer.on('request', function(req, response) {
            req.app = app;
            req.response = response;
            req.value = {};
            app.router.main(req);
        });
        app.httpServer.listen(app.config.port);
    }
});

Basically I define everything that is global under a variable called app . I connect the the database and create an http server and then I put app into the request object ( req ) for the event handler. I also put the response object ( response ) and an empty values object ( value ) under req .

So now, if I call the router function with app.router.main(req) , I only need to pass req to it and I still have access to all the global stuff as well as the request, response and any other values relevant to the request. It seems to work correctly.

My questions on this approach are:

  1. Is there a simpler way of getting to all my objects when I need them?
  2. Will the passing of the req object everywhere have a significantly detrimental effect on performace?
  3. Can this cause unforeseen issues relating to the database connection, request, response or any other parts of my app?
  1. Is there a simpler way of getting to all my objects when I need them?

    Bundling everything under one object doesn't seem like the best design choice to me. Sure, I can accept that req and res are almost always linked together, so for sure feel free to put req.res = res , but app ?

    Furthermore your app shouldn't really change; so you shouldn't need to constantly pass it around; once should be enough.

    I'd consider adding an export which accepts the app context to the modules of your program which need them.

     var app; module.exports = { init: function (_app) { app = _app; }, something: function (req) { // use req, you've got app if you need it. } } 
  2. Will the passing of the req object everywhere have a significantly detrimental effect on performace?

    No, nothing serious. You're only passing a reference to the object, not the object itself. If you were keeping track of all reqs on a persistent object (such as app ) you'd have the JavaScript equivalent of a memory leak, but that doesn't apply here.

  3. Can this cause unforeseen issues relating to the database connection, request, response or any other parts of my app?

    Not that I can think of.

    If you're constantly having to pass context objects around, I'd double check that you haven't got a poor module structure, or are over-modularizing your code.


FWIW, even if your aren't using express or connect, there's nothing wrong with looking at their codebase and seeing how they solved the problem; they're both open source ( https://github.com/visionmedia/express , https://github.com/senchalabs/connect )

The simpler way would be to just use a framework. Failing that, constructors/initializers for the entire module. Or just putting things in one file for the most part, 'cause modules aren't really good for that sort of thing.

An example of an initializer for the entire module, by the way, would be:

app.router = require('./router').create(app);
var app;

module.exports.create = function(_app) {
    app = _app;
    return module.exports;
};

And no, passing it around won't have any noticeable effect on performance, compared to just about anything else.

Hm i nearly always just some sort of singelton i can require whenever i need it lets say you got:

app.js

module.exports = exports = {
    start: function(config) {
         this.database = new database(config.database);
         this.webserver= http.createServer();
    }
 }

now you got to set up your routes say and maybe each of them got hist own file if you need your database object for instance you simple would do.

var db = require('app.js').database;

imho this works pretty well and gives you access to important stuff whereever you need it :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM