Express: How to pass app-instance to routes from a different file?

后端 未结 8 1045
误落风尘
误落风尘 2020-11-29 16:34

I want to split up my routes into different files, where one file contains all routes and the other one the corresponding actions. I currently have a solution to achieve thi

相关标签:
8条回答
  • 2020-11-29 16:49

    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....

    0 讨论(0)
  • 2020-11-29 16:50

    Or just do that:

    var app = req.app
    

    inside the Middleware you are using for these routes. Like that:

    router.use( (req,res,next) => {
        app = req.app;
        next();
    });
    
    0 讨论(0)
  • 2020-11-29 16:53

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

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

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

    0 讨论(0)
  • 2020-11-29 16:54

    Like I said in the comments, you can use a function as module.exports. A function is also an object, so you don't have to change your syntax.

    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;
    
    0 讨论(0)
  • 2020-11-29 16:56
    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. to avoid passing app instance everywhere, instead, passing routes to where the app is
    // 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
    

    The final 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}));
    
    0 讨论(0)
  • 2020-11-29 16:57

    Node.js supports circular dependencies.
    Making use of circular dependencies instead of require('./routes')(app) cleans up a lot of code and makes each module less interdependent on its loading file:


    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
    


    routes/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 update-----
    Express 4.0 fixed the usecase for defining routes by adding an express.router() method!
    documentation - http://expressjs.com/4x/api.html#router

    Example from their new generator:
    Writing the route:
    https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
    Adding/namespacing it to the app: https://github.com/expressjs/generator/blob/master/templates/js/app.js#L24

    There are still usecases for accessing app from other resources, so circular dependencies are still a valid solution.

    0 讨论(0)
提交回复
热议问题