为节点应用程序设置正确的结构

时间:2017-06-19 14:27:17

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

简介

到目前为止,我有三个文件,一个test.js是一个文件,我已经构建了三个有效的函数。

但是现在我正在尝试使用MVC或至少某种模式来构建。现在我router.jsapp.js

问题

我应该将test.js中的承诺函数放在我的config.jsserver.js或其他内容中,我只是对人们如何做到这一点以及构建NodeJS的正确方法感兴趣。

  1. server.js
  2. 在这里启动服务器并将路由应用到我的应用程序

    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
    2. 在这里我建立我的路线

      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
      2. 这里是一系列函数列表,它们是获取数据和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);
            });
        };
        

1 个答案:

答案 0 :(得分:2)

我推荐的结构是将server.js以外的所有内容放在lib目录中,这样您的所有应用都是lib/server.js - 其他所有内容都是package.json,依赖项在node_modules(在npm install上创建,而不是在回购中),.gitignore,为Travis,Circle,Heroku或您正在使用的任何服务配置文件,有些{{1}等等。

现在,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是加载中间件(如正文解析器等)的最小代码,创建快速应用程序并设置端口和名称的变量,然后使用由lib/app.js导出的路由器:

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.jslib/controllers/index.js - 就像路由一样。

然后我会在所有测试中添加顶级lib/controllers/*.jsspectest目录。测试可能要求您的tests在其上运行测试,而无需监听实际的TCP端口 - 这些将使用实际控制器测试您的路由。其他测试需要lib/app并对您的实用程序运行一些单元测试等。请务必使用lib/utilistanbul等工具来计算测试覆盖率。

数据库模式和数据模型将转移到nyclib/schemaslib/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; 的路线。