在 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,有小错误请见谅。如果您需要进一步说明,请告诉我。
干杯,
布伦南
我要全力以赴,只使用节点来做一个项目。这很有趣,但有时我会迷失其中,当我感到困惑时,我想尝试获得理解,这样我就能正确地构建它,而不会感到不知所措。不管怎样,问题来了:
我有 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,有小错误请见谅。如果您需要进一步说明,请告诉我。
干杯, 布伦南