web-dev-qa-db-fra.com

Express: Comment passer d'instance d'application à des itinéraires à partir d'un fichier différent?

Je souhaite diviser mes itinéraires en différents fichiers, un fichier contenant tous les itinéraires et l'autre les actions correspondantes. J'ai actuellement une solution pour y parvenir, mais j'ai besoin de rendre l'instance d'application globale pour pouvoir y accéder dans les actions. Ma configuration actuelle ressemble à ceci:

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.

};

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

Cependant, cette configuration a un gros problème: j'ai une base de données et une instance d'application que je dois transmettre aux actions (contrôleurs/*. Js). La seule option à laquelle je pouvais penser, est de rendre les deux variables globales, ce qui n'est pas vraiment une solution. Je veux séparer les itinéraires des actions parce que j'ai beaucoup d'itinéraires et que je les veux dans un endroit central.

Quel est le meilleur moyen de transmettre des variables aux actions tout en séparant les actions des itinéraires?

98
Claudio Albertin

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

La variable d'application créée en appelant express() est définie dans les objets requête et réponse.

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

158
Feng

Comme je l'ai dit dans les commentaires, vous pouvez utiliser une fonction comme module.exports. Une fonction est aussi un objet, vous n'avez donc pas besoin de changer votre syntaxe.

app.js

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

controllers.js

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

contrôleurs/index.js

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

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

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

module.exports = controllers;
26
mihai

Ou simplement faire ça:

var app = req.app

à l'intérieur du middleware que vous utilisez pour ces itinéraires. Comme ça:

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

Pour la base de données, séparez le service d'accès aux données qui effectuera tout le travail de base de données avec une API simple et évitera l'état partagé.

La séparation de routes.setup ressemble à une surcharge. Je préférerais placer un routage basé sur la configuration. Et configurez les itinéraires en .json ou avec des annotations.

0
Eldar Djafarov

Disons que vous avez un dossier nommé "contollers".

Dans votre app.js, vous pouvez mettre ce 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]");

... et ...

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

dans vos contrôleurs, vous aurez le fichier "ping.js" avec ce code:

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

Et c'est ça ....

0
Radu Gheorghies