我想将路由分成不同的文件,其中一个文件包含所有路由,另一个文件包含相应的操作。我目前有一个解决方案来实现这一点,但是我需要让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');
});
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.
};
控制器/ 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
};
然而,这个设置有一个很大的问题:我有一个数据库 - 我需要传递给操作的app-instance(controllers / * .js)。我能想到的唯一选择是将两个变量都变为全局变量,而这并非真正的解决方案。我想将路线与行动分开,因为我有很多路线,并希望它们位于中心位置。
将变量传递给操作但将操作与路径分开的最佳方法是什么?
答案 0 :(得分:155)
使用req.app
,req.app.get('somekey')
通过调用express()
创建的应用程序变量在请求和响应对象上设置。
答案 1 :(得分:94)
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
<小时/> 路由/ 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更新-----
新发电机的示例:
写路线:
https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
添加/命名空间到应用程序:
https://github.com/expressjs/generator/blob/master/templates/js/app.js#L24
仍有用于从其他资源访问应用程序的用例,因此循环依赖关系仍然是有效的解决方案。
答案 2 :(得分:26)
就像我在评论中所说,你可以使用一个函数作为module.exports。函数也是一个对象,因此您不必更改语法。
app.js
var controllers = require('./controllers')({app: app});
controllers.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;
答案 3 :(得分:4)
或者只是这样做:
var app = req.app
您正在使用这些路由的中间件内部。像那样:
router.use( (req,res,next) => {
app = req.app;
next();
});
答案 4 :(得分:0)
对于数据库分离出数据访问服务,它将使用简单的API完成所有数据库工作并避免共享状态。
分离routes.setup看起来像开销。我宁愿放置基于配置的路由。并在.json中或使用注释配置路由。
答案 5 :(得分:0)
Let's say that you have a folder named "contollers".
In your app.js you can put this code:
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]");
... and ...
router.get('/ping', controllers.ping.pinging);
in your controllers forlder you will have the file "ping.js" with this code:
exports.pinging = function(req, res, next){
console.log("ping ...");
}
And this is it....
答案 6 :(得分:0)
// app.js
let db = ...; // your db object initialized
const contextMiddleware = (req, res, next) => {
req.db=db;
next();
};
app.use(contextMiddleware);
// 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');
});
另一个版本:您可以根据自己的需要对此进行自定义,例如添加发布请求
// 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}));
答案 7 :(得分:0)
如果您要将应用程序实例传递给 Node-Typescript 中的其他人,
选项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))
选项2 :借助class
// index.ts
import express, { Application } from 'express';
import { Routes } from './routes';
const app: Application = express();
const rotues = new Routes(app)
...
在这里,我们将在Routes Class的构造函数中访问该应用程序
// 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 }