[node.js] 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');
});

route.js :

exports.setup = function(app, controllers) {

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

};

controllers / index.js :

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

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

controllers / posts.js :

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

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

그러나이 설정에는 큰 문제가 있습니다. 작업 (controllers / *. js)에 전달해야하는 데이터베이스 및 앱 인스턴스가 있습니다. 내가 생각할 수있는 유일한 옵션은 두 변수를 모두 전역으로 만드는 것인데, 이는 실제로 해결책이 아닙니다. 경로가 많고 중앙에 위치하기를 원하기 때문에 작업에서 경로를 분리하고 싶습니다.

작업에 변수를 전달하고 경로에서 작업을 분리하는 가장 좋은 방법은 무엇입니까?



답변

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

호출 express()에 의해 생성 된 애플리케이션 변수 는 요청 및 응답 객체에 설정됩니다.

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


답변

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


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


—– 2014 년 4 월 업데이트 —–
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

여전히 다른 리소스에서 앱에 액세스하는 사용 사례가 있으므로 순환 종속성은 여전히 ​​유효한 솔루션입니다.


답변

주석에서 말했듯이 함수를 module.exports로 사용할 수 있습니다. 함수도 객체이므로 구문을 변경할 필요가 없습니다.

app.js

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

controllers.js

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

controllers / index.js

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

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

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

module.exports = controllers;


답변

아니면 그냥하세요 :

var app = req.app

이러한 경로에 사용중인 미들웨어 내부. 그렇게 :

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


답변

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

컨트롤러 이전 버전에는 다음 코드와 함께 “ping.js”파일이 있습니다.

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

그리고이게 ….


답변

  1. 모든 컨트롤러에 db 객체를 전달하지 않고 모든 컨트롤러에 액세스 할 수 있도록하려면 db 객체를 모든 req 객체에 연결하는 애플리케이션 수준 미들웨어를 만든 다음 모든 컨트롤러에서 액세스 할 수 있습니다.
// 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');
});

다른 버전 : 게시 요청 추가와 같이 필요에 따라 맞춤 설정할 수 있습니다.

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


답변

데이터베이스의 경우 모든 DB 작업을 간단한 API로 수행하고 공유 상태를 피하는 데이터 액세스 서비스를 분리합니다.

route.setup을 분리하는 것은 오버 헤드처럼 보입니다. 대신 구성 기반 라우팅을 배치하고 싶습니다. .json 또는 주석으로 경로를 구성합니다.