希望有人可以在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”的内容时,它会按预期填充,但在运行时它显示为空。我确定这是一个异步问题 - 任何帮助都非常感谢!
答案 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);
}
}});