希望有人可以在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);
Run Code Online (Sandbox Code Playgroud)
当我在redis中检查"newset"的内容时,它会按预期填充,但在运行时它显示为空.我确定这是一个异步问题 - 任何帮助非常感谢!
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);
});
}
});
});
});
Run Code Online (Sandbox Code Playgroud)
有些库有一个内置的等价物forEach,允许你指定一个完成循环时要调用的函数.如果没有,你必须手动跟踪已经有多少回调,并smembers在最后一个回调后调用.
| 归档时间: |
|
| 查看次数: |
3949 次 |
| 最近记录: |