我希望通过将查询功能化为具有适当任务名称的函数来“功能化”我的查询。
我想避免将所有内容放在req, res
函数(我的控制器)中,而是将它们放入各种类型的“模型”中,即另一个将导入并用于运行函数的JavaScript文件执行查询并代表控制器返回结果。
假设我对查询有以下设置:
UserController.js
exports.userAccount = function(req, res, next) {
var queryText = "\
SELECT *\
FROM users\
WHERE id = $1\
";
var queryValues = [168];
pg.connect(secrets.DATABASE_URL, function(err, client, done) {
client.query(queryText, queryValues, function(err, result) {
res.render('pathToSome/page', {
queryResult: result.rows
});
});
});
}
在这里,当我在查询中时,我基本上重定向并呈现包含数据的页面。这很好。但是我想要取出所有pg.connect
和client.query
代码并将其移动到单独的文件中以作为模型导入。我想出了以下内容:
UserModel.js
exports.findUser = function(id) {
// The user to be returned from the query
// Local scope to 'findUser' function?
var user = {};
var queryText = "\
SELECT *\
FROM users\
WHERE id = $1\
";
var queryValues = [id];
pg.connect(secrets.DATABASE_URL, function(err, client, done) {
client.query(queryText, queryValues, function(err, result) {
// There is only ever 1 row returned, so get the first one in the array
// Apparently this is local scope to 'client.query'?
// I want this to overwrite the user variable declared at the top of the function
user = result.rows;
// Console output correct; I have my one user
console.log("User data: " + JSON.stringify(user));
});
});
// I expect this to be correct. User is empty, because it was not really
// assigned in the user = result.rows call above.
console.log("User outside of 'pg.connect': " + JSON.stringify(user));
// I would like to return the user here, but it's empty!
return user;
};
我正在调用我的模型函数:
var user = UserModel.findUser(req.user.id);
查询以这种方式执行完全正常 - 除了没有正确分配user
对象(我假设范围问题),我无法理解进行。
目标是能够从控制器调用函数(如上所述),让模型执行查询并将结果返回给控制器。
我错过了一些明显明显的东西吗?
答案 0 :(得分:3)
pgconnect
是异步调用。在继续下一行之前,不是等待数据从数据库返回,而是在Postgres回答之前继续执行程序的其余部分。因此,在上面的代码中,findUser
返回一个尚未填充的变量。
为了使其正常工作,您必须向findUser
函数添加回调。 (我在之前的编辑中告诉你错误:调用pg.connect中的done
参数,以便将连接释放回连接池。)最终结果应如下所示:
exports.findUser = function(id, callback) {
var user = {};
var queryText = "SELECT FROM users WHERE id = $1";
var queryValues = [id];
pg.connect(secrets.DATABASE_URL, function(err, client, done) {
client.query(queryText, queryValues, function(err, result) {
user = result.rows;
done(); // Releases the connection back to the connection pool
callback(err, user);
});
});
return user;
};
你使用它,不是这样的:
var user = myModule.findUser(id);
但是像这样:
myModule.findUser(id, function(err, user){
// do something with the user.
});
如果你要执行几个步骤,每个步骤都依赖于先前异步调用的数据,那么你最终将会遇到令人困惑的Inception风格的嵌套回调。有几个异步库可以帮助您使这些代码更具可读性,但最受欢迎的是npm的async
模块。