【问题标题】:Node.js & Node-Postgres: Putting Queries into ModelsNode.js 和 Node-Postgres:将查询放入模型
【发布时间】:2014-06-12 03:18:52
【问题描述】:

我想将我的查询“功能化”,方法是将它们放入具有适合任务名称的函数中。

我想避免将所有内容都放在 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 对象没有被正确分配(我假设 scope 问题),我无法弄清楚。

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

我在这里遗漏了什么明显的东西吗?

【问题讨论】:

    标签: javascript node.js postgresql


    【解决方案1】:

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

    【讨论】:

    • 感谢您的回答 - 我忘记了 done 电话;但是,在pg.connect 函数之外,我仍然得到一个空的user 对象。我只是不确定从pg.connect/client.query 获得结果的正确方法是...有人会认为done(results) 会这样做,但这不是我所看到的。
    • 由于 findUser 包含一个异步方法,这也使其异步,因此您不能使用它来分配像var user = findUser(id) 这样的变量。它也需要回调。我将编辑我的答案。
    • 太棒了!我想我只是不明白异步任务的概念。我正在考虑在这个项目中使用async 模块,但是没有足够的 need 用于它。我在node-postgres wiki(文档)中也没有看到任何关于异步的内容,所以我不知道从哪里开始。感谢您的帮助!
    • 我知道这是一篇旧帖子......但我想知道为什么最后一个语句给出了“返回用户”......我认为这是多余的,因为“用户”正在在回调中发送...?只是好奇:) 似乎是一个非常好的代码,我打算使用它。
    猜你喜欢
    • 2016-03-18
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    相关资源
    最近更新 更多