【问题标题】:Setting correct structure for a node app为节点应用程序设置正确的结构
【发布时间】:2017-06-19 14:27:16
【问题描述】:

简介

到目前为止,我有三个文件,一个test.js 是一个文件,我在其中构建了三个可以工作的函数。

但现在我正在尝试使用 MVC 或至少某种模式来构建结构。所以现在我router.js 和app.js

问题

我是否应该将来自 test.js 的 promise 函数放入我的 config.js 或 server.js 或其他东西中,我只是对人们如何做到这一点以及构建 NodeJS 的正确方法感兴趣。

  1. server.js

在这里启动服务器并将路由应用到我的应用程序

var configure = require('./router');
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;

// get an instance of router
var router = express.Router();
configure(router);

app.listen(port);
console.log('Server has started!! ' + port);

// apply the routes to our application
app.use('/', router);
  1. config.js

在这里我建立我的路线

module.exports = function (router) {

    // route middleware that will happen on every request
    router.use(function (req, res, next) {

        // log each request to the console
        console.log(req.method, req.url);

        // continue doing what we were doing and go to the route
        next();
    });

// home page route (http://localhost:8080)
    router.get('/', function (req, res) {
        res.send('im the home page!');
    });

// sample route with a route the way we're used to seeing it
    router.get('/sample', function (req, res) {
        res.send('this is a sample!');
    });


// about page route (http://localhost:8080/about)
    router.get('/about', function (req, res) {
        res.send('im the about page!');
    });

// route middleware to validate :name
    router.param('name', function (req, res, next, name) {
        // do validation on name here
        console.log('doing name validations on ' + name);

        // once validation is done save the new item in the req
        req.name = name;
        // go to the next thing
        next();
    });

// route with parameters (http://localhost:8080/hello/:name)
    router.get('/hello/:name', function (req, res) {
        res.send('hello ' + req.params.name + '!');
    })

    // app.route('/login')

    // show the form (GET http://localhost:8080/login)
        .get('/login', function (req, res) {
            res.send('this is the login form');
        })

        // process the form (POST http://localhost:8080/login)
        .post('/login', function (req, res) {
            console.log('processing'); // shows on console when post is made
            res.send('processing the login form!'); // output on postman
        });
};
  1. test.js

这里是一系列函数,它们是获取数据和 API 密钥的承诺链

(小函数,多个函数之一)

var firstFunction = function () {
    return new Promise (function (resolve) {
        setTimeout(function () {
            app.post('/back-end/test', function (req, res) {
                console.log(req.body);
                var login = req.body.LoginEmail;
                res.send(login);
                resolve({
                    data_login_email: login
                });
            });
            console.error("First done");
        }, 2000);
    });
};

【问题讨论】:

  • 实际上你的 config.js 根本不是配置,而是路由。所以称它们为 routes.js 并将 express.Router 直接导入 router.js 而不是传递它。
  • 知识加分,谢谢
  • 更好地使用官方文档中的这种方法expressjs.com/en/guide/routing.html#express-router
  • 感谢@jstice4all 现在调查

标签: javascript node.js express design-patterns model-view-controller


【解决方案1】:

我推荐的结构是将除server.js 之外的所有内容放在lib 目录中,因此您的所有应用程序都是lib/ 加上server.js - 其他所有内容都是package.json,依赖于node_modules(创建于npm install ,不在 repo 中)、.gitignore、Travis、Circle、Heroku 或您正在使用的任何服务的配置文件,一些 README.md 之类的东西。

现在,server.js 只是最低要求,需要lib/app:

const app = require('./lib/app');

并使用类似以下内容启动服务器:

const server = app.listen(app.get('port'), () => {
  logger.info('%s listening on port %s', app.get('name'), app.get('port'));
});
server.on('error', (err) => {
  logger.error(err.message || err);
  process.exit(1);
});

logger 是一些更高级别的记录器,例如 Winston 或类似的东西。

就是这样。现在,lib/app.js 是加载中间件(如正文解析器等)的最少代码,创建 express 应用并设置端口和名称的变量,然后使用由lib/routes 导出的路由器:

const routes = require('./routes');
// ...
app.use('/', routes);

lib/app 应该足以用于使用supertest 之类的工具进行测试,但它不会侦听任何端口 - server.js 会。这对于简化测试很重要。

lib/routes 导出的路由器用于一切,您可以从单个lib/routes.js 文件开始,然后根据需要将其转换为lib/routes/index.js 以及lib/routes 中的多个文件。

路由只定义实际路由和输入验证,例如模块。 express-validation 并注册由 lib/controllers 导出的控制器 - 可以以 lib/controllers.js 开头并根据需要转换为 lib/controllers/index.js 加上 lib/controllers/*.js - 就像路由一样。

然后我会添加顶级 spec 或 test 或 tests 目录,所有测试都在其中。测试可以要求您的 lib/app 在其上运行测试,而无需侦听实际的 TCP 端口 - 这些将使用实际控制器测试您的路由。其他测试需要lib/util 并在您的实用程序等上运行一些单元测试。确保使用istanbul 或nyc 等工具来计算测试覆盖率。

数据库模式和数据模型将转到lib/schemas 和lib/models,lib/util 中的一些实用程序助手,lib/config 中的一些配置加载代码等。

这是一种非常灵活的布局,效果很好。您可以从几个文件开始:

README.md
LICENSE.md
package.json
server.js
lib/app.js
lib/routes.js
lib/controllers.js
lib/config.js

等等。并根据需要轻松将所有 xxx.js 文件转换为 xxx/index.js 以及整个文件夹中较小的 xxx/*.js 文件。

与您的方法的主要区别在于,我建议导出路由器并由更高级别的路由器使用它们,而不是将高级路由器传递到较低级别的模块中,这些模块导出需要路由器工作的功能。

所以而不是:

const moreSpecific = require('more-specific');
const moreGeneral = express.Router();
moreSpecific(moreGeneral);

然后更具体:

module exports = (router) => {
  router.use('/abc/xyz', ...);
};

我建议在文件中导出更具体的路由器,例如routes/abc.js:

const router = express.Router();
router.use('/xyz', ...);
module exports = router;

然后是更通用的路由器,例如在routes/index.js:

const abc = require('abc');
const router = express.Router();
router.use('/abc', abc);
// and export the main router for other modules like app.js to use:
module.exports = router;

拥有像/abc/xyz 这样的路线。

【讨论】:

  • 不错的答案! , 对了,我会通读这个,一旦我回复你。谢谢,一旦我无法接受这种工作方式,我仍在尝试更改我的应用程序以使用此结构。我可以看到它的可扩展性和增长空间如何 +1
猜你喜欢
  • 2015-08-12
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 1970-01-01
  • 2012-12-19
  • 2010-09-22
相关资源
最近更新 更多