Express: 如何从不同的文件传递应用程序实例到路由?

我想把我的路由分割成不同的文件,其中一个文件包含所有的路由,另一个文件包含相应的操作。我目前有一个解决方案来实现这一点,但我需要使应用程序实例全局,以便能够访问它的行动。 我现在的设置是这样的:

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');
});

路线:

exports.setup = function(app, controllers) {


app.get('/', controllers.index);
app.get('/posts', controllers.posts.index);
app.get('/posts/:post', controllers.posts.show);
// etc.


};

控制器/index.js:

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


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

控制器/posts.js:

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


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

然而,这个设置有一个大问题: 我有一个数据库和一个应用程序实例,我需要传递给操作(控制器/* 。Js).我能想到的唯一选择,就是让两个变量都是全局的,这不是一个真正的解决方案。我想把路线和动作分开,因为我有很多路线,我想把它们放在一个中心位置。

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

109842 次浏览

对于数据库独立的数据访问服务,将用简单的 API 完成所有数据库工作,并避免共享状态。

分开路线,设置看起来像是开销。我更愿意放置一个基于配置的路由。中配置路由。Json 或带注释的。

正如我在评论中所说,您可以使用一个函数作为 module.export。函数也是一个对象,所以不需要改变语法。

应用程序

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

控制器 JS

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

控制器/index.js

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


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


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


module.exports = controllers;

使用 req.appreq.app.get('somekey')

The application variable created by calling express() is set on the request and response objects.

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

Js 支持循环依赖。使用循环依赖关系代替需求(’。路由’)(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


路线/索引

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');


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

来自他们的新发电机的例子:
编写路由: < br/> < a href = “ https://github.com/Expressjs/Generator/blob/master/template/js/ways/index.js”> https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
在应用程序中添加/命名空间: Https://github.com/expressjs/generator/blob/master/templates/js/app.js#l24

仍然有从其他资源访问应用程序的用例,所以循环依赖仍然是一个有效的解决方案。

假设您有一个名为“ controller”的文件夹。

在 app.js 中,你可以输入以下代码:

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]");

还有..。

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

在您的控制器文件夹中,您将拥有带有以下代码的文件“ ping.js”:

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

就是这个。

或者就这么做:

var app = req.app

在中间件中使用这些路由,像这样:

router.use( (req,res,next) => {
app = req.app;
next();
});
  1. To make your db object accessible to all controllers without passing it everywhere: make an application-level middleware which attachs the db object to every req object, then you can access it within in every controller.
// app.js
let db = ...;  // your db object initialized
const contextMiddleware = (req, res, next) => {
req.db=db;
next();
};
app.use(contextMiddleware);
  1. 避免到处传递应用程序实例,而是传递到应用程序所在位置的路由
// routes.js  It's just a mapping.
exports.routes = [
['/', controllers.index],
['/posts', controllers.posts.index],
['/posts/:post', controllers.posts.show]
];


// app.js
var { routes }    = require('./routes');
routes.forEach(route => app.get(...route));
// You can customize this according to your own needs, like adding post request

最后的 app.js:

// app.js
var express   = require('express');
var app       = express.createServer();


let db = ...;  // your db object initialized
const contextMiddleware = (req, res, next) => {
req.db=db;
next();
};
app.use(contextMiddleware);


var { routes }    = require('./routes');
routes.forEach(route => app.get(...route));


app.listen(3000, function() {
console.log('Application is listening on port 3000');
});

Another version: you can customize this according to your own needs, like adding post request

// routes.js  It's just a mapping.
let get = ({path, callback}) => ({app})=>{
app.get(path, callback);
}
let post = ({path, callback}) => ({app})=>{
app.post(path, callback);
}
let someFn = ({path, callback}) => ({app})=>{
// ...custom logic
app.get(path, callback);
}
exports.routes = [
get({path: '/', callback: controllers.index}),
post({path: '/posts', callback: controllers.posts.index}),
someFn({path: '/posts/:post', callback: controllers.posts.show}),
];


// app.js
var { routes }    = require('./routes');
routes.forEach(route => route({app}));

If you want to pass an app-instance to others in 节点-类型脚本 :

选择1:import(进口时)的帮助下

//routes.ts
import { Application } from "express";
import { categoryRoute } from './routes/admin/category.route'
import { courseRoute } from './routes/admin/course.route';


const routing = (app: Application) => {
app.use('/api/admin/category', categoryRoute)
app.use('/api/admin/course', courseRoute)
}
export { routing }

然后导入并通过应用程序:

import express, { Application } from 'express';


const app: Application = express();
import('./routes').then(m => m.routing(app))

Option 2: With the help of class

// index.ts
import express, { Application } from 'express';
import { Routes } from './routes';




const app: Application = express();
const rotues = new Routes(app)
...

在这里,我们将访问路由类的构造函数中的应用程序

// routes.ts
import { Application } from 'express'
import { categoryRoute } from '../routes/admin/category.route'
import { courseRoute } from '../routes/admin/course.route';


class Routes {
constructor(private app: Application) {
this.apply();
}


private apply(): void {
this.app.use('/api/admin/category', categoryRoute)
this.app.use('/api/admin/course', courseRoute)
}
}


export { Routes }
var express = require('express');


var router = express.Router();


router.get('/', function(req, res, next) {
console.log(req.app); // use req.app to get app instance ;


res.render('index', { title: 'Express' });


});


module.exports = router;