隐藏

node.js redis 异步查询

发布:2023/11/2 23:14:56作者:管理员 来源:本站 浏览次数:532

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

[点击复制代码] Java


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”的内容时,它按预期填充,但在运行时它显示为空。我确定这是一个异步问题 - 非常感谢任何帮助!


请您参考如下方法:


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


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

[点击复制代码] Java


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。