Gikkman Gikkman - 5 days ago 5
Node.js Question

ExpressJS - router module with parameters

I've been toying with NodeJS and Express for a few days, and it is pretty cool. But I've run into an issue I cannot get my head around, so I'm hoping someone else out there can help me clear this up.

I know that I can declare a module, and then pass parameters into this module via the

require
method.

--- App.js ----
var foo = require('./modules/Foo.js');
foo.config();
var bar= {}
require('./modules/Bar.js)(bar, foo)

--- Bar.js ---
module.exports = function(Bar, Foo) {
Bar.act = function(){
Foo.do();
}
}


I think this is a much cleaner design than having to require
Foo
in every module that would require using it. I also don't have to do initialization in each module that requires it.

But then comes the
Router
, and I can't really understand how it works. Most examples out there requires the router in each module, something like this:

--- App.js ----
var index = require('./views/index.js');
app.use('/', index);

--- Index.js ---
var express = require('express');
var router = express.Router();
var foo = require('../modules/Foo.js);

foo.config();

router.get('/', function (req, res) {
foo.do();
res.render('index');
})

module.exports = router


But then, I need to require all modules used in
index.js
manually. What I would really want to do is something like this:

--- App.js ----
var foo = require('../modules/Foo.js);
foo.config();
var index = require('./views/index.js')(foo);
app.use('/', index);

--- Index.js ---
var express = require('express');
var router = express.Router();

module.exports = function(foo){
router.get('/', function (req, res) {
foo.do();
res.render('index');
})
}


But writing it this way, the compiler tells me "Router.use() requires middleware, got a undefined". I can sorta see where this error comes from, (the
module.exports
does not return an object) but so how do I structure my code so that I can pass parameters to a module that in the end will export a Router middleware? I want to require and initialize
Foo
in one place, then pass it to all router modules that uses it. Is it possible somehow?

Answer

You almost got it, you just need to return the Router.

A fixed index.js could look like this:

var express = require('express');

module.exports = function(foo){
    var router = express.Router();

    router.get('/', function (req, res) {
        foo.do();
        res.render('index');
    });

    return router;
}

Notice the additional ; and the return.

I've also moved the instantiation of the router to the function. In node modules are cached, you can require the same module multiple times and they will all share their global variables. This can lead to unexpected results. In your case you'll overwrite the router.get handler every time and the same instance of Foo would be used for every request.

Comments