在 Express REST API 中使用 OOP 的最佳方式?

Best Way to Use OOP in Express REST API?

我要全力以赴,只使用节点来做一个项目。这很有趣,但有时我会迷失其中,当我感到困惑时,我想尝试获得理解,这样我就能正确地构建它,而不会感到不知所措。不管怎样,问题来了:

我有 REST API 使用 Express 和 mysql。我设置了 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);

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

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

的相关部分

routes/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);
...

};

controllers/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 等

谢谢。

这里发生了很多事情,但我会解决这个问题。

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

routes/users.js

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

所以我们在这里所做的是消除对您的 app/log 中间件的依赖。

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

app.js

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

这也是您可以放置​​您选择的任何中间件(日志记录、正文解析、错误处理等)的地方。

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

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

controllers/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),而无需更改一大堆东西!

现在,用户模型可能如下所示:

/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,有小错误请见谅。如果您需要进一步说明,请告诉我。

干杯, 布伦南