【发布时间】:2014-04-29 15:37:57
【问题描述】:
我正在使用 node.js 和 redis。我有一个带有一堆键的 redis 数据库。像这样的:
用户/克里斯/药水 用户/皮特/药水 用户/克里斯/种族 用户/皮特/种族 用户/克里斯/武器 用户/皮特/武器
我想做一个 redis 调用,它检索所有用户统计信息,将统计信息放入 JS 对象中,然后将其传递给客户端以在浏览器中显示字符统计信息。使用 javascript,我将 u 处的用户名 chris 注入到 redis 调用中,如下所示:
KEYS user/u/*
返回:
1) "user/chris/weapon"
2) "user/chris/race"
3) "user/chris/potion"
现在我可以遍历这些结果,使用 GET 获取每个键的值,然后创建一个 javascript 对象。看起来超级简单,所以我编写了代码。我很快就遇到了使用 forEach 的问题:
var redis = require('redis');
var client = redis.createClient();
exports.getUserObject = function(requesteduser, callback) {
var userstats = {}; // the object to hold the user stats once retrieved from the db
client.KEYS('user/' + requesteduser + '/*', function(err, replies) {
replies.forEach(function (reply, i) {
client.GET(reply, function(err, value) {
// get the key name so we can populate a js object
var n = reply.lastIndexOf('/');
var key = reply.substring(n + 1, reply.length);
userstats[key] = value;
console.dir(userstats);
callback(null, userstats); // parent expects (err, userstats)
});
});
});
}
运行时输出如下:
{ weapon: 'twosword' }
{ weapon: 'twosword', race: 'elf' }
{ weapon: 'twosword', race: 'elf', potion: 'mana' }
callback(null, userstats) 被调用了 3 次。多次调用回调会有问题,因为最终回调会触发数据被发送到客户端。
我想我知道发生了什么。 client.GET 运行了三次,因为我要求它这样做。 replies数组有3个元素,所以每次client.GET的结果进来,都会调用回调。
我需要做的是让 forEach 循环完成对所有 redis 键的迭代,一旦完成,就调用一次回调。我尝试先用 Promise 解决这个问题,然后用 async,因为 async 有 async.each。我被困在解决这两个问题上。我现在又回到了原点,我确信我必须对 forEach 做一些不同的事情才能取得进展。
我怎样才能做到这一点?
【问题讨论】:
-
将
callback(null, userstats);移到forEach之外不能解决问题吗? -
@Greg,这是我尝试的第一件事,但是因为 client.GET(?) 是一个异步函数,所以在 client.GET 返回第一个值之前调用回调。我最终得到一个空的 userstats 对象。
-
当然!忘记了异步;)
标签: javascript node.js asynchronous redis