node.js redis异步查询

时间:2012-04-18 11:17:52

标签: node.js redis

希望有人可以在node-redis上协助(简单)异步问题。我正在尝试从redis数据库中的哈希加载一个集合,然后再使用该填充集合。这是代码片段: -

var redis_client = redis.createClient(REDIS_PORT, REDIS_URL); 

redis_client.hgetall(target_hash,function(e,o){

    Object.keys(o).forEach(function(target){

        // get the "name" from the hash         
        redis_client.hget(o[target],"name",function(e,o){
        if (e){
                 console.log("Error occurred getting key: " + e);
              }
        else {
                 redis_client.sadd("newset",o);
             }
    });

});

// the following line prints nothing - why ?? 

redis_client.smembers("newset",redis.print);

当我在redis中检查“newset”的内容时,它会按预期填充,但在运行时它显示为空。我确定这是一个异步问题 - 任何帮助都非常感谢!

2 个答案:

答案 0 :(得分:7)

hgetall是一个异步调用:当它从redis服务器收到回复时,它最终会调用你的回调function (target) { ... }。但是在你的脚本中,它实际上会立即返回。由于hgetall返回非常快,Node将立即运行下一个语句smembers。但此时sadd语句还没有运行(即使你的系统非常快,因为还没有上下文切换)。

您需要做的是确保在执行所有可能的smembers调用之前未调用sadd。 redis_client提供multi函数,允许您排队所有sadd个调用,并在完成所有调用后运行回调。我没有测试过这段代码,但你可以试试这个:

var redis_client = redis.createClient(REDIS_PORT, REDIS_URL);

redis_client.hgetall(target_hash, function(e, o) {
  var multi = redis_client.multi();
  var keys = Object.keys(o);
  var i = 0;

  keys.forEach(function (target) {
    // get the "name" from the hash     
    redis_client.hget(o[target], "name", function(e, o) {
      i++;
      if (e) {
        console.log("Error occurred getting key: " + e);
      } else {
        multi.sadd("newset", o);
      }

      if (i == keys.length) {
        multi.exec(function (err, replies) {
          console.log("MULTI got " + replies.length + "replies");
          redis_client.smembers("newset", redis.print);
        });
      }
    });
  });
});

某些库具有内置等效的forEach,允许您指定在完成循环时要调用的函数。如果没有,您必须手动跟踪已经有多少回调,并在最后一个回调后调用smembers

答案 1 :(得分:1)

除非您确实需要交易,否则不应使用multi。

只保留交易的计数器并在最终回调中调用smembers

var redis_client = redis.createClient(REDIS_PORT, REDIS_URL); 
var keys = Object.keys(o);
var i = 0;
redis_client.hgetall(target_hash,function(e,o){

    Object.keys(o).forEach(function(target){

        // get the "name" from the hash         
        redis_client.hget(o[target],"name",function(e,o){
        i++
        if (e){
                 console.log("Error occurred getting key: " + e);
              }
        else {
                 redis_client.sadd("newset",o);
                 if (i == keys.length) {
                    redis_client.smembers("newset", redis.print);
                 }

         }});