user1790300 user1790300 - 2 months ago 17
Node.js Question

Node.JS: issue with handling multiple modules for large node application

I am a newbie to Node.JS and began looking for best practice articles, etc. to make sure my node.js code was unit test friendly and followed the node.js best practices. While researching I came across the following code examples:

app.js:

module.exports = function (flights) {
var express = require('express');
var routes = require('./routes')(flights);
var path = require('path');
var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(function (req, res, next) {
res.set('X-Powered-By', 'Flight Tracker');
next();
});
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}

app.get('/flight/:number', routes.flight);
app.put('/flight/:number/arrived', routes.arrived);
app.get('/list', routes.list);

return app;
}


server.js:

var http = require('http'),
flights = require('./data'),
app = require('./app')(flights);

http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});


module(index.js):

var Flight = function () {
this.data = {
number: null,
origin: null,
destination: null,
departs: null,
arrives: null,
actualDepart: null,
actualArrive: null
};

this.fill = function (info) {
for(var prop in this.data) {
if(this.data[prop] !== 'undefined') {
this.data[prop] = info[prop];
}
}
};

this.triggerDepart = function () {
this.data.actualDepart = Date.now();
};

this.triggerArrive = function () {
this.data.actualArrive = Date.now();
};

this.getInformation = function () {
return this.data;
};
};

module.exports = function (info) {
var instance = new Flight();

instance.fill(info);

return instance;
};


routes(index.js):

module.exports = function (flights) {
var flight = require('../flight');

for(var number in flights) {
flights[number] = flight(flights[number]);
}

var functions = {};

functions.flight = function(req, res){
var number = req.param('number');

if (typeof flights[number] === 'undefined') {
res.status(404).json({status: 'error'});
} else {
res.json(flights[number].getInformation());
}
};

functions.arrived = function (req, res) {
var number = req.param('number');

if (typeof flights[number] === 'undefined') {
res.status(404).json({status: 'error'});
} else {
flights[number].triggerArrive();
res.json({status: 'done'});
}
};

functions.list = function (req, res) {
res.render('list', {
title: 'All Flights',
flights: flights});
};

return functions;
};


While I like how this is organized alot, I do not see an efficient way to handle multiple modules in this scenario. Let's say I have additional modules for User, Initerary, etc. This seems like it could become chaotic quickly as I began to add routes to the app.js file, not to mention how many potential parameters would need to be passed into app.js. What if I have a large rest layer that required 20 or more modules? I am looking for any doc or links or examples demonstrating a clean way I should do this in node.js.

Answer

Granularize and encapsulate using sub routers with express.Router(). Each router then becomes it's own module that you pull in making it so that you don't have to add every single route explicitly in app.js.

User.js

"use strict";

// Create a router
var express = require("express"),
    router = express.Router();

router.get("/", function (req, res, next) {
    // All your User logic
    res.send([
        {
            name: "Bob"
        },
        {
            name: "John"
        }
    ]);
});

router.get("/:number", function (req, res, next) {
    res.send({
        name: "Bob"
    });
});

router.post("/", function (req, res, next) {
    res.send({
        name: "New Guy"
    });
});

module.exports = router;

App.js

var app = express();
app.use("/user", require("./User"));

Now you can GET /user, GET /user/SOME_ID, and POST to /user. It's also simple if you want to move the sub route around to somewhere else because the methods defined for the user route are relative.

Comments