In a redis datastore I have a list of keys, I want to iterate over that list of keys and get those values from redis. The catch is I am using an event driven language, javascript via node.js
If javascript were procedural I could do this
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);
}
But, I cannot, therefor.. I do this?
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()
});
};
This seams wrong, because, instead of executing all requests at once, and then letting callbacks insert onto list, I am forcing a sequential call sequence. What happens if there are 1000s of keys?
Could I do this some how?
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);
});
};
Declare an object variable before you dispatch your calls within the for loop. Each call can than add its result into the object.
You then need code to wait for all calls to be done. This might help you: https://gist.github.com/464179
Example:
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();
});
}
}
Please note that call()
should be your async database function, that executes the callback on result.