【问题标题】:Javascript event sequence, pg, postgresql, why?Javascript事件序列,pg,postgresql,为什么?
【发布时间】:2015-08-07 08:25:28
【问题描述】:

我正在尝试用 express 编写一个 javascript 文件来与 postgresql 数据库通信。更准确地说,我想编写一个将 SQL 作为输入参数并返回字符串化 json 的函数。考虑到这些表大小,我可以假设内存不是问题。这是为私营企业制作内部使用工具的有偿工作。

我最近的尝试涉及将值放入全局变量的查询回调,但即使这样仍然失败,因为最外层的函数在定义 json 字符串之前返回。以下是相关代码:

var dbjson;

function callDB(q) {
    pg.connect(connectionString, function(err, client, done) {
        if (err) {
            console.error('error fetching client from pool', err);
        } else {
            client.query(q, [], function(err, result) {
                client.query('COMMIT');
                done();
                if (err) {
                    console.error('error calling query ' + q, err);
                } else {
                    dbjson = JSON.stringify(result.rows);
                    console.log('1 ' + dbjson);
                }
                console.log('2 ' + dbjson);
            });
            console.log('3 ' + dbjson);
        }
        console.log('4 ' + dbjson);
    });
    console.log('5 ' + dbjson);
}

我测试的 SQL 是"select id from users"。 相关的控制台输出为:

5 undefined
GET /db/readTable?table=users 500 405.691 ms - 1671
3 undefined
4 undefined
1 [{"id":1},{"id":2},{"id":3},{"id":4}]
2 [{"id":1},{"id":2},{"id":3},{"id":4}]

为什么控制台日志按照它们的顺序出现? 它们的顺序是一致的。

我试图编写一个轮询循环来等待在调用者中使用 setTimeout 设置全局变量,然后在回调中清除超时,但我认为这失败了,因为 javascript 是单线程的,我的循环不允许其他活动进行。也许我做错了。

虽然我知道我可以让每个函数处理自己的数据库连接和错误日志记录,但我真的很讨厌重复相同的代码。

有什么更好的方法来做到这一点?

我在表达和 javascript 方面相对较新,但在其他语言方面经验丰富。

【问题讨论】:

  • 我相信 console.logs 是按这个顺序出现的,因为 pg.connectclient.query 都是异步的。
  • 注意代码的更新缩进。您的所有查询/结果处理都在回调函数中完成,这意味着.connect() 触发、返回并下降到您的5。然后随着事情的开始,代码的其他部分开始运行。例如所有这些代码都是异步的。
  • 这是为私人企业制作内部使用工具的有偿工作。。感谢您披露这一点,感谢。我对JS方面的了解不够,恐怕无法解释这一点。
  • 感谢您的回答。我相信他们是正确的。对于遇到这个问题的其他人,我只是通过在每个需要它的函数中重复对数据库的调用来解决它,有时是多个层次。

标签: javascript json postgresql express pg


【解决方案1】:

以下行的出现将为您破坏一切:

client.query('COMMIT');

您正在尝试以同步方式执行异步命令,并且您正在调用done(),在该查询有机会执行之前释放连接。这种无效断开连接的结果将是不可预测的,尤其是因为在这种情况下您没有处理任何错误。

你为什么一开始就在那里打电话给COMMIT?这本身看起来完全无效。 COMMIT 用于关闭当前事务,你甚至没有在那里打开它,所以它不存在。

在异步代码使用和数据库方面存在一些误解。如果你想在这两个方面都有一个好的开始,我建议你看看pg-promise

【讨论】:

    猜你喜欢
    • 2017-07-06
    • 2021-08-01
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 2011-09-06
    • 2018-02-11
    相关资源
    最近更新 更多