如何使用NodeJS和Express从app.js中分离路由和模型

时间:2013-10-27 15:43:00

标签: node.js express

我正在使用Node和Express创建应用。但是,我可以看到管理app.js内的所有路径很快就会变得很困难。我已将所有模型放在子目录/models中。

这是我的应用当前结构:

app.js
models
  -- products
  -- customers
  -- ...
public
views
node_modules

app.js

var express = require('express'),
    routes = require('./routes'),
    user = require('./routes/user'),
    http = require('http'),
    path = require('path'),
    EmployeeProvider = require('./models/employeeprovider').EmployeeProvider,
    Products = require('./models/products').Products,
    Orders = require('./models/orders').Orders,
    Customers = require('./models/customers').Customers,
    checkAuth = function(req, res, next) {
      if (!req.session.user_id) {
        res.send('You are not authorized to view this page');
      } else {
        next();
      }
    };

var app = express();

然后是一些配置,如portviews目录,渲染引擎等

再向下app.js我有路线:

app.get('/product/edit', auth, function(req, res) {
  Products.findAll(function(error, prds) {
    res.render('product_edit', {
      title: 'New Product',
      products: prds
    });
  });
});

在顶部我将models/products.js的内容分配给变量,一切正常。但是,保留app.js内的所有路线并不理想。但是,如果我将路线移至routes/product.js并加载Products模型:

var prod = require('../models/products.js');

我收到一条错误消息,指出该对象没有方法findAll

我做错了什么?如何从app.js删除路线?

3 个答案:

答案 0 :(得分:32)

从快递4.x Router开始,以支持您的案例。

  

路由器对象是中间件和路由的隔离实例。您可以将其视为“迷你应用程序”,只能执行中间件和路由功能。每个Express应用程序都有一个内置的应用程序路由器。

来自expressjs site的示例:

// routes/calendarRouter.js

var express  = require('express');
var router = express.Router();

// invoked for any requested passed to this router
router.use(function(req, res, next) {
  // .. some logic here .. like any other middleware
  next();
});

// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
  // ..
});

module.exports = router;

然后在app.js:

// skipping part that sets up app

var calendarRouter = require('./routes/calendarRouter');

// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', calendarRouter);

// rest of logic

答案 1 :(得分:28)

由于我不喜欢重复,这就是我的所作所为:

// app.js
//...
var routes = requireDir('./routes'); // https://www.npmjs.org/package/require-dir
for (var i in routes) app.use('/', routes[i]);
//...

路由中的每个文件都是:

// routes/someroute.js
var express  = require('express');
var router   = express.Router();

router.get('/someroute', function(req, res) {
    res.render('someview', {});
});

module.exports = router;

通过这种方式,您可以避免像这样的长重复列表:

app.use('/'           , require('./routes/index'));
app.use('/repetition' , require('./routes/repetition'));
app.use('/is'         , require('./routes/is'));
app.use('/so'         , require('./routes/so'));
app.use('/damn'       , require('./routes/damn'));
app.use('/boring'     , require('./routes/boring'));

编辑:这些长示例假设每个路径文件包含以下内容:

var router = express.Router();
router.get('/', function(req, res, next) {
    // ...
    next();
});
module.exports = router;

所有这些都可以挂载到“root”,但对于它们来说是“root”,实际上是给app.use的特定路径,因为你可以将路由挂载到特定路径(这也支持像使用正则表达式指定路径,Express对于您可以使用路由做什么非常简洁。

答案 2 :(得分:21)

我可以建议你这个文件结构(根据Modular web applications with Node.js and Express from tjholowaychuk):

app.js
   modules
      users
         index.js
         model.js
      users-api
         index.js
      static-pages
         index.js

user-apistatic-pages导出expressjs应用程序,您可以轻松地将它们安装到app.js. 在users模块中,您可以描述一些数据访问操作以及有关使用用户实体进行操作的所有方法(如创建,更新等)。我们的API模块将使用所有这些方法。

以下是app.js文件的示例代码(没有常用的快递,只有来自不同模块的安装路径):

var express = require('express');
var app = express();

// mount all the applications
app.use('/api/v1', require("user-api"));
app.use(require("static-pages"));

app.listen(3000);

要以这种方式使用您的模块,您必须像NODE_PATH=modules node app.js一样启动您的应用程序(我将此行放在脚本部分的package.json文件中)。

以下是users模块的示例代码:

<强> index.js

User = require("./model");

module.exports = {
    get: function(id, callback) {
        User.findOne(id, function(err, user) {
           callback(err, user);
        });
    },
    create: function(data, callback) {
        // do whatever with incoming data here
        data = modifyDataInSomeWay(data);
        var newUser = new User(data);
        newUser.save(function(err, savedUser) {
            // some logic here
            callback(err, savedUser); 
        });
    }
};

model.js (当然还有Mongoose的东西!)

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var User = new Schema({
    firstname   : {type: String, required: false},
    lastname    : {type: String, required: false},
    email       : {type: String, required: true}
});

module.exports = mongoose.model('user', User);

user-api模块的示例(这是关于分离路径和模型的答案的主要部分)。

var users = require("users");

var express = require("express");
var app = module.exports = express(); // we export new express app here!

app.post('/users', function(req, res, next) {
    // try to use high-level calls here
    // if you want something complex just create another special module for this
    users.create(req.body, function(err, user) {
        if(err) return next(err); // do something on error
        res.json(user); // return user json if ok
    });
});

static-pages的例子。如果您不打算构建一种REST接口,您可以创建几个仅呈现页面的模块。

var express = require("express");
var app = module.exports = express(); // we export new express app here again!

app.get('/', function(req, res, next) {
    res.render('index', {user: req.user});
});

app.get('/about', function(req, res, next) {
    // get data somewhere and put it in the template
    res.render('about', {data: data});
});

当然,你可以用模块做任何你想做的事情。关于expressjs的主要想法是使用许多小应用程序而不是单个应用程序。

关于nodejs模块,您可以阅读stackoverflowdocs

希望这有帮助。