Express: ¿Cómo pasar la instancia de la aplicación a las rutas desde un archivo diferente?

Quiero dividir mis rutas en diferentes archivos, donde un archivo contiene todas las rutas y el otro las acciones correspondientes. Actualmente tengo una solución para lograr esto, sin embargo, necesito hacer que la instancia de la aplicación sea global para poder acceder a ella en las acciones. Mi configuración actual se ve así:

app.js:

var express = require('express'); var app = express.createServer(); var routes = require('./routes'); var controllers = require('./controllers'); routes.setup(app, controllers); app.listen(3000, function() { console.log('Application is listening on port 3000'); }); 

routes.js:

 exports.setup = function(app, controllers) { app.get('/', controllers.index); app.get('/posts', controllers.posts.index); app.get('/posts/:post', controllers.posts.show); // etc. }; 

controladores / index.js:

 exports.posts = require('./posts'); exports.index = function(req, res) { // code }; 

controladores / posts.js:

 exports.index = function(req, res) { // code }; exports.show = function(req, res) { // code }; 

Sin embargo, esta configuración tiene un gran problema: tengo una base de datos y una instancia de aplicación que necesito pasar a las acciones (controladores / *. Js). La única opción que se me ocurre es hacer que ambas variables sean globales, lo cual no es realmente una solución. Quiero separar las rutas de las acciones porque tengo muchas rutas y las quiero en un lugar central.

¿Cuál es la mejor manera de pasar variables a las acciones pero separar las acciones de las rutas?

Node.js admite dependencias circulares.
Hacer uso de dependencias circulares en lugar de require (‘./ routes’) (aplicación) limpia una gran cantidad de código y hace que cada módulo sea menos interdependiente en su archivo de carga:


app.js

 var app = module.exports = express(); //now app.js can be required to bring app into any file //some app/middleware setup, etc, including app.use(app.router); require('./routes'); //module.exports must be defined before this line 

routes / index.js

 var app = require('../app'); app.get('/', function(req, res, next) { res.render('index'); }); //require in some other route files...each of which requires app independently require('./user'); require('./blog'); 

—– 04/2014 actualización —–
Express 4.0 solucionó el caso de uso para definir rutas agregando un método express.router ()
documentación – http://expressjs.com/4x/api.html#router

Ejemplo de su nuevo generador:
Escribiendo la ruta:
https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
Agregar / nombrar espacios en la aplicación: https://github.com/expressjs/generator/blob/master/templates/js/app.js#L24

Todavía hay usos para acceder a la aplicación desde otros recursos, por lo que las dependencias circulares siguen siendo una solución válida.

Use req.app , req.app.get('somekey')

La variable de aplicación creada llamando a express() se establece en los objetos de solicitud y respuesta.

Ver: https://github.com/visionmedia/express/blob/76147c78a15904d4e4e469095a29d1bec9775ab6/lib/express.js#L34-L35

Como dije en los comentarios, puede usar una función como module.exports. Una función también es un objeto, por lo que no tiene que cambiar su syntax.

app.js

 var controllers = require('./controllers')({app: app}); 

controllers.js

 module.exports = function(params) { return require('controllers/index')(params); } 

controladores / index.js

 function controllers(params) { var app = params.app; controllers.posts = require('./posts'); controllers.index = function(req, res) { // code }; } module.exports = controllers; 

O simplemente haz eso:

 var app = req.app 

dentro del Middleware que estás usando para estas rutas. Como eso:

 router.use( (req,res,next) => { app = req.app; next(); }); 

Para el servicio de acceso a datos separado de la base de datos que hará todo el trabajo DB con API simple y evitar el estado compartido.

Separating routes.setup se ve como una sobrecarga. Preferiría colocar un enrutamiento basado en la configuración en su lugar. Y configure las rutas en .json o con anotaciones.

Digamos que tienes una carpeta llamada “controladores”.

En tu app.js puedes poner este código:

 console.log("Loading controllers...."); var controllers = {}; var controllers_path = process.cwd() + '/controllers' fs.readdirSync(controllers_path).forEach(function (file) { if (file.indexOf('.js') != -1) { controllers[file.split('.')[0]] = require(controllers_path + '/' + file) } }); console.log("Controllers loaded..............[ok]"); 

… y …

 router.get('/ping', controllers.ping.pinging); 

en tus controladores, tendrás el archivo “ping.js” con este código:

 exports.pinging = function(req, res, next){ console.log("ping ..."); } 

Y esto es …