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

Wag*_*sUK 32 node.js express

我正在使用Node和Express创建一个应用程序.但是,我可以看到很快就很难管理放在里面的所有路线app.js.我已将所有模型放在子目录中/models.

这是我的app当前结构:

app.js
models
  -- products
  -- customers
  -- ...
public
views
node_modules
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

然后一些配置一样port,views目录,渲染引擎等.

再往下app.js我有路线:

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

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

var prod = require('../models/products.js');
Run Code Online (Sandbox Code Playgroud)

我得到一个错误,说该对象没有方法findAll.

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

Aiv*_*ras 32

由于快递4.x版的Router加入到支持您的案件.

路由器目的是中间件和路由的分离的实例.你可以把它看成是一个"迷你应用程序",只能够执行中间件和路由功能.每个Express应用程序都有一个内置的应用程序路由器.

从实例expressjs网站:

// 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;
Run Code Online (Sandbox Code Playgroud)

然后,在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
Run Code Online (Sandbox Code Playgroud)


Cam*_*tin 29

既然我不喜欢重复,这就是我的所作所为:

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

路由中的每个文件都是:

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

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

module.exports = router;
Run Code Online (Sandbox Code Playgroud)

这样你可以避免像这样的长重复列表:

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'));
Run Code Online (Sandbox Code Playgroud)

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

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

所有这些都可以挂载到"root",但对于它们来说是"root",实际上是给定的特定路径app.use,因为你可以将路由挂载到特定的路径(这也支持像使用正则表达式指定路径,Express关于你可以用路由做什么很完美).

  • 这似乎是一个不错的主意,但由于我是 Node.js 和 Express 的新手,所以我有一个问题。我看到您省去了编写每个单独路由(/repetition、/is 等)的麻烦,但不会`app.use('/', routes[i]);` 只设置所需的路由路线?你最后给出的长例子是不同的,即它是`app.use('/route', require('./routes/route'));`。我希望这是有道理的。 (2认同)

Pet*_*nko 21

我可以建议你这个文件结构(根据Node.js的模块化Web应用程序和来自tjholowaychuk的Express):

app.js
   modules
      users
         index.js
         model.js
      users-api
         index.js
      static-pages
         index.js
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

要以这种方式使用您的模块,您必须像这样启动您的应用程序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); 
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

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
    });
});
Run Code Online (Sandbox Code Playgroud)

和的例子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});
});
Run Code Online (Sandbox Code Playgroud)

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

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

希望这可以帮助.