【问题标题】:Asynchronous Database Queries with PostgreSQL in Node not working节点中使用 PostgreSQL 的异步数据库查询不起作用
【发布时间】:2013-12-01 01:46:55
【问题描述】:

使用 Node.js 和 node-postgres module 与数据库通信,我正在尝试编写一个函数,该函数接受一组查询和回调,并使用相同的数据库连接异步执行它们。该函数接受一个二维数组并调用它如下所示:

perform_queries_async([
  ['SELECT COUNT(id) as count FROM ideas', function(result) {
    console.log("FUNCTION 1");
  }],
  ["INSERT INTO ideas (name) VALUES ('test')", function(result) {
    console.log("FUNCTION 2");
  }]
]);

并且该函数遍历数组,为每个子数组创建一个查询,如下所示:

function perform_queries_async(queries) {
  var client = new pg.Client(process.env.DATABASE_URL);

  for(var i=0; i<queries.length; i++) {
    var q = queries[i];

    client.query(q[0], function(err, result) {
      if(err) {
        console.log(err);
      } else {
        q[1](result);
      }
    });
  }

  client.on('drain', function() {
    console.log("drained");
    client.end();
  });

  client.connect();
}

当我运行上面的代码时,我希望看到这样的输出:

FUNCTION 1
FUNCTION 2
drained

然而,输出奇怪地看起来像这样:

FUNCTION 2
drained
FUNCTION 2

不仅为两个请求调用了第二个函数,而且似乎在客户端的查询队列完成运行之前调用了排水代码......然而第二个查询仍然运行得很好,即使 @一旦事件被调用,987654326@ 代码表面上就杀死了客户端。

我已经为此烦恼了好几个小时。我尝试在我的示例数组中进行硬编码(因此删除了 for 循环),并且我的代码按预期工作,这让我相信我的循环存在一些我没有看到的问题。

任何关于为什么会发生这种情况的想法将不胜感激。

【问题讨论】:

    标签: node.js postgresql node-postgres


    【解决方案1】:

    最好使用异步模块来执行。它还将帮助您重用代码。并使代码更具可读性。我只是喜欢异步模块提供的自动功能 参考:https://github.com/caolan/async

    【讨论】:

      【解决方案2】:

      在现代 JavaScript 的闭包中正确捕获 q 变量的值的最简单方法是使用 forEach

      queries.forEach(function(q) {
          client.query(q[0], function(err, result) {
            if(err) {
              console.log(err);
            } else {
              q[1](result);
            }
          });
       });
      

      如果您不捕获该值,您的代码会在包含函数的上下文中反映q 具有的最后一个值,作为稍后执行的回调函数。

      forEach,通过使用回调函数隔离并捕获q 的值,以便内部回调正确评估它。

      【讨论】:

      • 啊,非常感谢,这非常有效。我仍然遇到“drained”没有出现在预期位置的问题,但显然这更多是 node-postgres 库的问题,而不是循环语法。
      【解决方案3】:

      著名的 Javascript 闭包/循环陷阱的受害者。在此处查看我的(和其他)答案:

      I am trying to open 10 websocket connections with nodejs, but somehow my loop doesnt work

      基本上,在执行回调时,q 被设置为输入数组的最后一个元素。绕过它的方法是动态生成闭包。

      【讨论】:

        猜你喜欢
        • 2018-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-09
        • 2019-05-27
        • 1970-01-01
        相关资源
        最近更新 更多