【问题标题】:Best Way to Use OOP in Express REST API?在 Express REST API 中使用 OOP 的最佳方式?
【发布时间】:2015-03-26 20:38:43
【问题描述】:

我将全力以赴,只使用节点做一个项目。这很有趣,但有时我会有点迷失,当我感到困惑时,我想尝试获得理解,所以我正确地构建它并且不要太不知所措。无论如何,这是问题所在:

我有使用 Express 和 mysql 的 REST API。我设置了mysql:

app.js

//Variables, move these to env
var dbOptions = {
    host: config.db_config.host,
    user: config.db_config.user,
    password: config.db_config.password,
    port: config.db_config.port,
    database: config.db_config.database
};
app.use(myConnection(mysql, dbOptions, 'single'));

然后我包含我的路由,将路由传递给应用程序和日志中间件,以便我可以在路由中使用它们:

app.js 续

var userRoute = require('./routes/users.js')(app,log);
app.use('/users', userRoute);

这实际上有点令人困惑,但现在我明白了,我必须将它们传递给模块才能让模块获取数据。

然后在我的路由文件中,我想使用一个对象,以便我可以在其他路由中使用相同的功能,但在用户文件中,以便使用与其他所有内容相同的连接池,或者至少不使用必须再次建立连接我必须将响应和请求传递给它?必须有更好的方法来做到这一点。这样真的很丑这是

的相关部分

路由/users.js

var User = require('../controllers/User.js');

module.exports = (function(app,log) {
var userR = express.Router();

userR.post('/register', function(req,res){
        var email = req.body.email;
        var password = req.body.password;
        var firstName = req.body.first_name;
        var lastName = req.body.last_name;
        var userId;

        try {
            var query;
            var status = 200;
            var response = '';

            var newUser = {
                email: email,
                password:password,
                first_name: firstName,
                last_name: lastName,
                password: password
            };

            var user = new User(req,res);

            user.register(newUser);
...

};

控制器/User.js

module.exports = function User(req,res) {
this.id = 0;
    this.register = function(newUser){

        var _this = this;
        var deferred = q.defer();
req.getConnection(function(err,connection){
...

这里一定有我遗漏的模式。我应该能够通过应用程序或其他东西并可以访问 req.getConnection 等。

谢谢。

【问题讨论】:

    标签: node.js rest oop express node-mysql


    【解决方案1】:

    这里发生了很多事情,但我会尝试一下。

    我的第一个建议是尽量让您的路由器保持纤薄。它没有标记,但我假设您提供的最大的 sn-p 代码是您的路由器。当然有很多意见,但如果我这样做,这就是我的路由器的样子。我假设您使用的是 Express 4x。

    路由/users.js

    var User = require('../controllers/user.js');
    var userRouter = express.Router();
    userRouter.post("/register", User.register);
    module.exports = userRouter;
    

    所以我们在这里所做的是消除了对您的应用程序/日志中间件的依赖。

    这意味着您的主文件(我通常称为 app.js)将如下所示:

    app.js

    var userRouter = require('./routes/users.js');
    app.use('/users', userRouter);
    

    您还可以在这里放置您选择的任何中间件(日志记录、正文解析、错误处理等)。

    在 Express 的更高版本中,上面的代码实际上将我们的 userRouter 挂载到“/users”。在这种情况下,您现在将拥有一个“/users/register”路由。

    所以现在既然我们已经提取了路由器的一些逻辑,我们必须把它放在某个地方。通常,路由器会与控制器通信,所以让我们看一下:

    控制器/user.js

    var User = require("../models/user.js")
    var register = function(req, res, next){
        var email = req.body.email;
        var password = req.body.password;
        var firstName = req.body.first_name;
        var lastName = req.body.last_name;
        var userId;
        var params = {
                email: email,
                password:password,
                first_name: firstName,
                last_name: lastName,
                password: password
            };
        var newUser = new User(params);
    
        try {
           newUser.register();
            // do other things...
        }
    };
    module.exports = {register: register};
    

    您会注意到的第一件事是我将拥有一个 UserModel 文件。通过这样做,我们将我们的模型对象与这条路线分离。假设我们有一个新的注册路线(可能其中一个有电子邮件+密码,另一个通过 FB 注册,我们必须存储不同的东西)。我们应该能够使用我们模型中指定的相同函数(在本例中为 user.register),而无需更改一大堆东西!

    现在,UserModel 可能如下所示:

    /models/user.js

    var connection = require("../lib/connection.js");
    var User = function(params){
       this.email = params.email;
       // ...etc
    };
    
    User.prototype.register = function(newUser){
        connection.getConnection(function(error, connection){
            //connection.doWhatever();
        });
    };
    
    module.exports = User;
    

    现在我们终于找到了您问题的核心。在顶部,您会看到我们有一个连接文件。这就是我们要放置所有与数据库相关的逻辑(如连接池)的地方。

    /lib/connection.js

    /*
    This will be in some JSON config we'll say
    var dbOptions = {
        host: config.db_config.host,
        user: config.db_config.user,
        password: config.db_config.password,
        port: config.db_config.port,
        database: config.db_config.database
    };
    
    */
    //This will depend on which version/module/db you're using, but here's what mine looks like
    var MySQL = require("mysql");
    var config = require("../config/db.json");
    connectionPool = MySQL.createPool({host: config.db_config.host, ...});
    
    var getConnection = function(done){
       connectionPool.getConnection(done);
    };
    
    module.exports = {getConnection: getConnection};
    

    因此,总而言之,我们现在不是将您的连接与您的请求对象一起传递,而是简单地将我们的短连接模块包含在我们所在的任何模型文件中,请求连接,并执行我们需要的任何处理。另请注意,您必须将连接释放回池中,但我会将其作为练习留给您:)。

    另外,我通常写 CoffeeScript,所以请原谅任何小错误。如果您需要进一步说明,请告诉我。

    干杯, 布伦南

    【讨论】:

    • 哇!好详细的回答,谢谢。我仍在消化这整件事,但这使得快速应用程序的结构更加清晰。我认为最让我困惑的是我正在使用的节点包“myConnection”扩展了请求对象以提供 mysql 功能,这实际上没有任何意义。看起来我根本不需要它。一个最初的问题:像您那样单独编写函数而不是模块导出通常是更好的做法吗?我刚刚将所有内容都包装在 module.exports = { ... } 中,再次感谢。
    • 啊,我不确定myConnection 位。我以前从未见过。这样做对我来说更有意义,因为不是每个请求都需要连接到数据库。我发现在底部导出所有内容更清洁,原因有两个。首先,你可以让你的代码更扁平,而不是立即开始深入一层。其次,假设您是一致的,您将知道在所有文件中查找导出的位置。如果您开始添加不想以其他方式导出的辅助方法,则情况并非如此。
    • 我很乐意回答任何其他问题,但如果您觉得我的回答有帮助,请不要忘记接受!
    • User.register 如何访问 req,res,next 而无需在路由的函数调用中传递它们?
    • User.register 是一个包含签名为 (req, res, next) 的函数的变量。路由器正在做的是将功能与路径相关联。 Here's a simple example of what's happening.
    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多