【问题标题】:How to separate the routes and models from app.js using NodeJS and Express如何使用 NodeJS 和 Express 将路由和模型从 app.js 中分离出来
【发布时间】:2017-08-08 00:21:13
【问题描述】:

我正在使用 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 中删除路由?

【问题讨论】:

标签: node.js express


【解决方案1】:

从 express 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

【讨论】:

  • 不应该是app.use('/calendar', require('./routes/x'));吗?
  • 当然@Brennen,已修改以使其更清晰。在我跳过routerrequired 的部分之前。
  • 看起来 calendarRouter.js 文件缺少一些导出?
  • 为什么 calenderRouter.js 文件中缺少 module.exports=router ?
【解决方案2】:

因为我不喜欢重复,所以我就是这样做的:

// 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 在路由方面非常简洁)。

【讨论】:

  • 这似乎是个好主意,但由于我是 Node.js 和 Express 的新手,我有一个问题。我看到您省去了编写每个单独路线(/repetition、/is 等)的麻烦,但app.use('/', routes[i]); 不会只在“/”路线上设置所需的路线吗?你最后给出的长例子是不同的,即app.use('/route', require('./routes/route'));。我希望这是有道理的。
  • @DarrylYoung 试图清理它,看看现在是否更有意义:)
  • 谢谢,@CamiloMartin!非常感谢。
  • 很高兴我能帮助@DarrylYoung!
  • 很好的答案!试图弄清楚我在module.exports.router 上做错了什么,而你用module.exports = router; 让我走上了正轨
【解决方案3】:

我可以建议你这个文件结构(根据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 文件的示例代码(没有常见的 express 东西,只安装来自不同模块的路由):

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

希望这会有所帮助。

【讨论】:

  • 我没有看到分离用户和用户api的逻辑...... api的东西应该在用户目录中,否则会很快变得复杂
  • @AlxVallejo 感谢您的评论!你在这个问题的上下文中是绝对正确的,但在我为模型和 API 使用单独文件夹的应用程序上下文中不是(它比这个超级简单的例子更复杂)。
  • 这个“用户”是从哪里来的? var users = require("users"); 来自?
  • @duardbr users 是一个用于处理用户实体的模块(您可以在我的帖子中找到一个示例)。它可以像 get/create/update/remove 一样简单,也可以包含任何复杂的逻辑和方法。
猜你喜欢
  • 2020-07-23
  • 2013-11-27
  • 1970-01-01
  • 2021-09-29
  • 2014-07-18
  • 1970-01-01
  • 2013-05-24
  • 2020-10-05
相关资源
最近更新 更多