Redis node.js - chaining calls to get user data

2019-09-06 19:25发布

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?

2条回答
疯言疯语
2楼-- · 2019-09-06 20:14

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);
    })
}
查看更多
聊天终结者
3楼-- · 2019-09-06 20:21

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.

查看更多
登录 后发表回答