问题
I have a database of users: profiles, products, configurations, and other things that a user could own. I'm trying to figure out a way to successfully chain my redis calls (a "getAll" function) so that I can return an object with all of these things, like:
user = {
profile: {},
products: {},
config: {},
...
}
Here is how I'm accessing them/ what I'm trying to do:
User.getAll = function(uid, next){
var user = {};
var multi = client.multi();
var key = 'user' + uid;
client.hgetall(key, function(err, profile){
user.profile = profile;
//signal that profile is ready
}
key = 'products:' + uid;
client.smembers(key, function(err, arr){
key = key + ':';
for (i=0; i < arr.length; i++){
multi.hgetall(key + arr[i]);
}
multi.exec(function(err, products){
user.products = products;
//signal that products is ready
}));
})
if (ready) { //obviously this isn't correct.
return next(null, user);
}
}
How can I resume after I've received all the data I want? Is event emitter the right way to go?
回答1:
I think that event emitter won't be a good choice here. You can keep track of all the calls, like that:
User.getAll = function(uid, next){
var requests = ["first", "second"];
var check_request = function(_key) {
var idx = requests.indexOf(_key);
if (idx!==-1) {
requests.splice(idx, 1);
}
if (!requests.length) {
next(user);
}
};
// ORIGINAL CODE + check_request
var user = {};
var multi = client.multi();
var key = 'user' + uid;
client.hgetall(key, function(err, profile){
user.profile = profile;
check_request("first");
}
key = 'products:' + uid;
client.smembers(key, function(err, arr){
key = key + ':';
for (i=0; i < arr.length; i++){
multi.hgetall(key + arr[i])
}
multi.exec(function(err, products){
user.products = products;
check_request("second");
}));
})
}
Obviously you will use something that makes more sense then requests = ["first", "second"];
, but I hope you get the idea.
Also have a look at async.js. It's a nice library which simplify that for you and it can do much more.
回答2:
I think you should check the async module. It's parallel flow control function will be perfect for you:
User.getAll = function(uid, next){
var user = {};
var multi = client.multi();
async.parallel([
function(callback){
// first task
var key = 'user' + uid;
client.hgetall(key, callback);
},
function(callback){
// second task
var key = 'products:' + uid;
client.smembers(key, function(err, arr){
if (err) return callback(err); // error check!!!
key = key + ':';
for (i=0; i < arr.length; i++){
multi.hgetall(key + arr[i]);
}
multi.exec(callback);
})
}
], function(err,res){
// async callback
if (err) return next(err); // error check!!!
user.profile = res[0];
user.products = res[1];
return next(null, user);
})
}
来源:https://stackoverflow.com/questions/15866568/redis-node-js-chaining-calls-to-get-user-data