Express:如何将app-instance传递给来自不同文件的路由?

Cla*_*tin 98 node.js express

我想将我的路由分成不同的文件,其中一个文件包含所有路由,另一个文件包含相应的操作.我目前有一个解决方案来实现这一点,但是我需要让app-instance全局能够在操作中访问它.我目前的设置如下:

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');
});
Run Code Online (Sandbox Code Playgroud)

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.

};
Run Code Online (Sandbox Code Playgroud)

控制器/ index.js:

exports.posts = require('./posts');

exports.index = function(req, res) {
  // code
};
Run Code Online (Sandbox Code Playgroud)

控制器/ posts.js:

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

exports.show = function(req, res) {
  // code
};
Run Code Online (Sandbox Code Playgroud)

但是,这个设置有一个很大的问题:我有一个数据库 - 我需要传递给操作的app-instance(controllers/*.js).我能想到的唯一选择是将两个变量都变为全局变量,而这并非真正的解决方案.我想将路线与行动分开,因为我有很多路线,并希望它们位于中心位置.

将变量传递给操作但将操作与路由分开的最佳方法是什么?

Fen*_*eng 159

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

通过调用创建的应用程序变量在express()请求和响应对象上设置.

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

  • 别忘了在app.js中调用`app.set('somekey',{})` (4认同)
  • 我对这种方式唯一的抱怨是,当你尝试运行 app.locals.authorized 时(不是在 main.js 中):`app.route('/something').get(app.locals.authorized)。 locals.authorized,function(req,res,next){});` 是不可能的,因为它在 req 范围之外。 (3认同)

Wil*_*ern 99

Node.js支持循环依赖.
使用循环依赖而不是require('./ routes')(app)清理了大量代码,并使每个模块在其加载文件上的相互依赖性降低:


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
Run Code Online (Sandbox Code Playgroud)


路线/ 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');
Run Code Online (Sandbox Code Playgroud)


----- 04/2014更新-----
Express 4.0通过添加express.router()方法修复了用于定义路由的用例!
文档 - http://expressjs.com/4x/api.html#router

来自他们的新生成器的示例:
编写路线:
https ://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
添加/命名空间到应用程序:https: //github.com /expressjs/generator/blob/master/templates/js/app.js#L24

仍有用于从其他资源访问应用程序的用例,因此循环依赖关系仍然是有效的解决方案.

  • 请非常小心(请阅读:不要做过去一个多小时来我一直在努力的工作),在`app.js`中,您需要路由文件_after_导出应用程序。循环的`require()`调用可能会造成真正的混乱,因此请确保您知道[它们如何工作](http://nodejs.org/docs/latest/api/modules.html#modules_cycles)! (2认同)

mih*_*hai 26

就像我在评论中所说的那样,你可以使用一个函数作为module.exports.函数也是一个对象,因此您不必更改语法.

app.js

var controllers = require('./controllers')({app: app});
Run Code Online (Sandbox Code Playgroud)

controllers.js

module.exports = function(params)
{
    return require('controllers/index')(params);
}
Run Code Online (Sandbox Code Playgroud)

控制器/ index.js

function controllers(params)
{
  var app = params.app;

  controllers.posts = require('./posts');

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

module.exports = controllers;
Run Code Online (Sandbox Code Playgroud)


asa*_*hez 6

或者只是这样做:

var app = req.app
Run Code Online (Sandbox Code Playgroud)

在用于这些路由的中间件中。像那样:

router.use( (req,res,next) => {
    app = req.app;
    next();
});
Run Code Online (Sandbox Code Playgroud)