NodeJS + redis给出了奇怪的结果

时间:2013-12-14 15:57:31

标签: node.js node-redis

也许结果并不奇怪,但我在1-2个月前开始使用Node,所以对我来说他们是......

我有一个循环,用于排除hgetall(Redis命令)返回的数组的每个其他值,在该循环中,我调用一个函数从另一个表中获取所有值,并将键存储在已排序的数组中。这比我想象的更难解释。这是我的代码:

Pastebin:http://pastebin.com/tAVhSUV1(或见下文)

function getInfo (cn, callback) {
        var anArray = [];
        redis_client.hgetall('chat_info:' + cn, function (err, vals) {
                if(err) { throw err; }
                for(i in vals) {
                        anArray.push(vals[i]);
                }
                return callback(anArray);
        });
}

redis_client.hgetall('chat_rooms:' + POST.chat_name, function (err, val) {
        if(err) { throw err; }
        var     vars = [],
                rArr = [];

        for (i in val) {
                vars.push(i);
        }
        for(var i = 0; i < vars.length; i += 1) {
                if(i%2 === 0) {
                        getInfo(vars[i], function (hej) {
                                rArr.push(hej);
                        });
                }
        }      
});

在整个循环之后执行从getInfo()调用的回调。我错过了什么吗?因为它不能那样做,对吧? (当我使用rArr(在循环之后)它是空的,nbBut如果我在回调中记录它,那么在循环之后之后所有其他内容都会被记录)

1 个答案:

答案 0 :(得分:0)

是的,这可能是正常的。

了解在hgetall调用后执行回调。这意味着当redis函数接收到某些内容时,它将调用回调函数。换句话说,所有回调都可以在以后执行。

由于javascript只能在一个线程中运行,因此对hgetall的调用应该是阻塞,因为它们来自for循环。但是你肯定使用异步IO。 for循环结束然后它将开始调用在javascript事件循环内排队的每个回调。

修改

不幸的是,要实现您要做的事情,您应该将代码包装在许多其他回调中。您可以使用此项目来简化:https://github.com/caolan/async

您应该可以使用npm install async安装它。

你必须做那样的事情:

function getInfo (cn) {
        return function(callback) {
            var anArray = [];
            redis_client.hgetall('chat_info:' + cn, function (err, vals) {
                if(err) { throw err; }
                for(i in vals) {
                        anArray.push(vals[i]);
                }
                return callback(anArray);
            });
        };
}

redis_client.hgetall('chat_rooms:' + POST.chat_name, function (err, val) {
        if(err) { throw err; }
        var     vars = [],
                rArr = [],
                callbacks = [];

        for (i in val) {
                vars.push(i);
        }

        for(var i = 0; i < vars.length; i += 1) {
                if(i%2 === 0) {
                        callbacks.push(getInfo(vars[i]));
                }
        }

        async.series(callbacks, function (err, results) {
           // Final code here
        });
});