Node.js& Node-Postgres:将查询放入模型中

时间:2014-06-11 17:25:33

标签: javascript node.js postgresql

我希望通过将查询功能化为具有适当任务名称的函数来“功能化”我的查询。

我想避免将所有内容放在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.connectclient.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对象(我假设范围问题),我无法理解进行。

目标是能够从控制器调用函数(如上所述),让模型执行查询并将结果返回给控制器。

我错过了一些明显明显的东西吗?

1 个答案:

答案 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模块。