javascript - 为 Node 应用程序设置正确的结构

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

简介

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

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

问题

我应该将 test.js 中的 Promise 函数放入我的 config.jsserver.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);
  • 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
            });
    };
    
  • test.js
  • 这里是一个函数列表,这些函数是获取数据和 API key 的一系列 promise

    (小函数,每个函数中的众多函数之一)

    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);
        });
    };
    

    最佳答案

    我推荐的结构是放置除 server.js 之外的所有内容。在lib目录,因此您的所有应用程序都是 lib/server.js - 其他一切都是package.jsonnode_modules 中的依赖项(在 npm install 上创建,而不是在存储库中), .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 导出的 Controller - 可以以 lib/controllers.js 开头并转换为lib/controllers/index.jslib/controllers/*.js根据需要 - 就像路线一样。

    然后我会添加顶级 spectesttests所有测试所在的目录。这些测试可能需要您的lib/app在其上运行测试而无需监听实际的 TCP 端口 - 这些将使用实际 Controller 测试您的路由。其他测试将需要 lib/util并对您的实用程序等运行一些单元测试。请确保使用类似 istanbul 的工具或nyc计算测试覆盖率。

    数据库模式和数据模型将转到 lib/schemaslib/modelslib/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 的路线.

    关于javascript - 为 Node 应用程序设置正确的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44633243/

    相关文章:

    javascript - NodeJS 应用程序的安全分发

    使用 Node.js 进行 Ajax 文件上传

    javascript - AngularJS - 从指令调用 Controller 函数

    javascript - JS 弹出窗口

    javascript - 如何使用浏览器查看页面源选项查看jquery附加数据?

    python - 面临导入错误: DLL load failed while implementing Microsoft azure iothub_service_client

    node.js - 如何 stub /监视模块中内部调用的外部方法?

    node.js - 为什么在通过 ngrok 建立隧道时会出现 CORS 错误?

    node.js - pug.compile() 找不到模板文件(res.render() 可以)

    javascript - 如何在 Bootstrap Modal 上使用 Vue.js 渲染插件 jQuery(如工具提示和 Switchery)?