【问题标题】:node.js / Postgres : Cannot assign value in scopenode.js / Postgres:无法在范围内赋值
【发布时间】:2011-06-17 15:33:44
【问题描述】:

在我的 node.js 应用程序中,我有以下代码来获取给定用户的最后一个标记。

 app.get('/user/:token/mark/last', function(req, res){
    var user_token   = req.params.id;

    // Mark to be returned
    var last_mark = 0;

    // Get user
    var get_user = client.query("SELECT id FROM user where user_token = $1", [user_token]);

    // Get mark: handle sensor retrieved
    get_user.on('row', function(row) {
      get_mark = client.query("SELECT * FROM mark WHERE user_id = $1 order by date desc limit 1", [row.id]);


      get_mark.on('row', function(mark) {
        last_mark = mark.value;
        console.log("LAST MARK:" + last_mark);    // OK IT DISPLAYS "LAST MARK:16"
      });

      // Error checking
      get_mark.on("error", function (err) {
        console.log("ERROR");
      });
    });

    // Check database errors
    get_user.on("error", function (err) {
      console.log("NO SUCH USER");
    });

    // Finalize
    get_user.on("end", function () {
      console.log("LAST MARK:" + last_mark);   // KO IT DISPLAYS "LAST MARK: 0"
    });
 })

问题是我没有得到正确的“last_mark”(我得到 0),就好像分配没有完成一样。

你有什么想法吗?

【问题讨论】:

  • 您确定在“row”回调之后调用了“end”回调吗?我希望内部client.query 关闭外部client.query,因为大多数数据库接口只允许每个连接一个活动语句。
  • @mu-is-too-short,是的,我之前已经使用过这种结构,内部请求没有任何问题。不过,我不必在嵌套请求中设置全局变量。
  • PostgreSQL 接口(如果我看的是正确的接口)有一个.query 调用队列,所以嵌套应该没问题。但是,我不知道事情会以什么顺序发生(甚至可以保证任何特定的顺序):'end' 事件会在内部查询执行任何操作之前还是之后触发?您是否考虑过使用 JOIN 重写查询以完全避免事件顺序问题?
  • @mu-is-too-short,你说得对,我只尝试一个 JOIN 查询。干杯,卢克
  • @mu-is-too-short,太好了,加入没问题。虽然仍然不太了解我的嵌套查询结构中发生了什么,但您的解决方案可能更好,您是对的。你能创建一个回复,以便我可以关闭这个问题吗?干杯

标签: postgresql node.js


【解决方案1】:

这不是我最好的答案,但您可以将您的两个查询替换为一个执行 JOIN 的查询:

select m.value
from mark m join user u on (m.user_id = u.id)
where user_token = $1
order by m.date desc
limit 1

这应该可以解决问题,让您继续工作。正如莱纳斯所说:

没有太大的问题是逃不掉的。

我仍然认为当触发内部“行准备就绪”事件和触发外部“查询完成”事件时存在某种时间问题。我希望在内部“行准备就绪”事件之前触发外部“结束”事件(但不可否认,我不熟悉 node.js 数据库接口)。您还可以将“处理last_mark”逻辑推送到“行准备就绪”回调中:

get_mark.on('row', function(mark) {
    // Call yet another callback to send `mark.value`
    // into the outside world.
});

这会在回调链中引入更多步骤,但在处理异步 API 时,这种事情是正常的。

【讨论】:

    【解决方案2】:

    声明变量时要小心,“last_mark”似乎在全局范围内(或至少在您发布的代码之外声明),由于回调的异步性质,这可能会导致意外行为,因为可能存在多个客户端之间的“竞争条件”可能会清除和设置相同的全局变量,而不是它们自己的本地实例。

    // Mark to be returned
    var last_mark = 0;
    

    【讨论】:

      猜你喜欢
      • 2014-07-24
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多