在redis数据存储区中,我有一个键列表,我想遍历该键列表并从redis中获取这些值。问题是我正在使用事件驱动的语言,javascript通过node.js
如果javascript是程序性的,我可以这样做
function getAll(callback) {
var list = redis.lrange(lrange('mykey', 0, -1);
for ( var i = 0; i < list.length; i+= 1 ) {
list[i] = redis.hgetall(list[i]);
}
callback(list);
}
但是,我不能,因为......我这样做?
function getAll(callback) {
redis.lrange('mykey', 0, -1, function(err, reply) {
// convert reply into messages
var list = [];
var index = -1;
var recurse = function() {
if ( index == reply.length ) {
callback(list);
} else {
redis.hgetall(reply[i], function(err, reply) {
list.push(reply);
index += 1;
recurse();
});
}
};
recurse()
});
};
这个接缝错了,因为,不是一次执行所有请求,而是让回调插入到列表中,我正在强制执行顺序调用序列。如果有1000个密钥怎么办?
我可以这样做吗?
function getAll(callback) {
redis.lrange('mykey', 0, -1, function(err, reply) {
// convert reply into messages
var list = [];
var insert = function(err, reply) {
list.push(reply);
};
for ( var i = 0; i < reply.length; i += 1 ) {
redis.hgetall(reply[i], insert);
}
??? how to block until finished ???
callback(list);
});
};
答案 0 :(得分:3)
???如何阻止直到完成???
你不能,如果你正在进行的调用是异步的话。你必须定义你的getAll
,期望它将异步完成,然后重新编写一下。
我不熟悉你正在制作的redis电话,但基本模式是:
function doTheBigThing(param, callbackWhenDone) {
asyncCallToGetList(param, function(result) {
var list = [];
asyncCallToGetNextEntry(result.thingy, receivedNextEntry);
function receivedNextEntry(nextResult) {
if (nextResult.meansWeAreDone) {
callback(list);
}
else {
list.push(nextResult.info);
asyncCallToGetNextEntry(result.thingy, receivedNextEntry);
}
}
});
}
打破这一点:
doBigThing
(您的getAll
)被调用。receivedNextEntry
,并使用用于检索条目的任何信息调用“获取下一个条目”函数,并将其作为回调传递。receivedNextEntry
存储它获得的条目,如果完成,则触发主要的“全部完成”回调;如果没有,它会发出下一个请求。很抱歉不能为您提供特定于redis的答案,但我认为映射是:
doBigThing
= getAll
asyncCallToGetList
= redis.lrange
asyncCallToGetNextEntry
= redis.hgetall
...但您使用redis.lrange
和redis.hgetall
的参数是什么,我恐怕不知道。
答案 1 :(得分:1)
在for循环中调度调用之前声明一个对象变量。每次调用都可以将其结果添加到对象中。
然后您需要代码来等待所有呼叫完成。这可能会对您有所帮助:https://gist.github.com/464179
示例:
function getAll(callback) {
var results = [];
var b = new Barrier(2, function() {
// all complete callback
callback();
}, function() {
// Aborted callback, not used here
});
var list = redis.lrange(lrange('mykey', 0, -1);
for ( var i = 0; i < list.length; i+= 1 ) {
//dispatch your call
call(function(foo){
results.push(foo);
b.submit();
});
}
}
请注意call()
应该是您的异步数据库函数,它会对结果执行回调。
答案 2 :(得分:1)
如果您发现自己需要经常使用这样的模式,那么您可能有兴趣尝试async.js library。使用async.js你可以这样写:
function getAll(callback) {
redis.lrange('mykey', 0, -1, function(err, reply) {
async.concat(reply, redis.hgetall, callback);
});
};
这基本上意味着“在'回复'中对每个项目调用hgetall然后将所有结果连接起来并传递给回调”。