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');
});
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
};
Однако эта настройка имеет большую проблему: у меня есть база данных и приложение-экземпляр, который мне нужно передать в действия (контроллеры/*. js). Единственный вариант, о котором я мог думать, - это сделать обе переменные глобальными, что на самом деле не является решением. Я хочу отделить маршруты от действий, потому что у меня много маршрутов и вы хотите их в центральном месте.
Какой лучший способ передать переменные в действия, но отделить действия от маршрутов?
Ответы
Ответ 1
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 -----
Express 4.0 установил usecase для определения маршрутов, добавив метод express.router()!
документация - http://expressjs.com/4x/api.html#router
Пример из своего нового генератора:
Написание маршрута:
https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
Добавление /namespacing в приложение:
https://github.com/expressjs/generator/blob/master/templates/js/app.js#L24
По-прежнему существуют возможности для доступа к приложению из других ресурсов, поэтому циклические зависимости все еще являются допустимым решением.
Ответ 2
Используйте req.app
, req.app.get('somekey')
Прикладная переменная, созданная вызовом express()
, устанавливается на объекты запроса и ответа.
Смотрите: https://github.com/visionmedia/express/blob/76147c78a15904d4e4e469095a29d1bec9775ab6/lib/express.js#L34-L35
Ответ 3
Как я уже сказал в комментариях, вы можете использовать функцию как 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;
Ответ 4
Или просто сделайте это:
var app = req.app
внутри промежуточного ПО, которое вы используете для этих маршрутов. Например:
router.use( (req,res,next) => {
app = req.app;
next();
});
Ответ 5
Для отдельной базы данных Служба доступа к данным, которая будет работать со всеми БД с простым API и избегать совместного использования.
Разделение маршрутов .setup выглядит как служебные. Вместо этого я предпочел бы размещать маршрутизацию на основе конфигурации. И настройте маршруты в .json или с аннотациями.
Ответ 6
Скажем, что у вас есть папка с именем "contollers".
В вашем приложении 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);
в вашем контроллере forlder у вас будет файл "ping.js" с помощью этого кода:
exports.pinging = function(req, res, next){
console.log("ping ...");
}
И это он....