请问我可以问一些关于node和redis的控制流问题的建议吗?(又名Python编码器试图习惯JavaScript)
我不明白为什么client.smembers
和client.get
(Redis查找)需要回调,而不是简单的语句-它使生活变得非常复杂。
基本上,我想查询一个集合,然后当我有了集合的结果时,我需要对每个结果执行get。* 当我得到所有数据 * 时,我需要将其广播回客户端。
目前,我在两个回调函数中使用全局对象来实现这一点,这看起来很混乱。我甚至不确定它是否安全(代码会等待一个client.get
完成后再启动另一个吗?)
当前代码如下所示:
var all_users = [];
// Get all the users for this page.
client.smembers("page:" + current_page_id, function (err, user_ids ) {
// Now get the name of each of those users.
for (var i = 0; i < user_ids.length; i++) {
client.get('user:' + user_ids[i] + ':name', function(err, name) {
var myobj = {};
myobj[user_ids[i]] = name;
all_users.push(myobj);
// Broadcast when we have got to the end of the loop,
// so all users have been added to the list -
// is this the best way? It seems messy.
if (i === (user_ids.length - 1)) {
socket.broadcast('all_users', all_users);
}
});
}
});
字符串
但是这看起来很混乱。这真的是最好的方法吗?我怎么能确定在调用socket.broadcast
之前已经执行了所有的查找?
4条答案
按热度按时间eblbsuwk1#
我不明白为什么
client.smembers
和client.get
(Redis查找)需要是回调而不是简单的语句--这让生活变得非常复杂。这就是Node。(我敢肯定,这个主题在这里讨论了足够多的时间,看看其他问题,它肯定在那里)
如何确保在调用
socket.broadcast
之前已执行了所有查找?这就是回调函数中
err
的含义。这有点像Node的标准-回调函数中的第一个参数是error object(如果一切正常,则为null
)。因此,只需使用类似以下的内容来确保没有错误发生:字符串
但这看起来很乱。
你会习惯的。我发现当代码的格式很好,项目的结构很巧妙的时候,这是很好的。
其他方式有:
mefy6pfw2#
如果你完全不喜欢写回调风格的东西,你可能想试试streamlinejs:
字符串
请注意,这种变体的缺点是一次只能获取一个用户名。此外,您仍然应该了解此代码的实际用途。
jhdbpxl93#
Async是一个很棒的库,你应该看看。为什么?干净的代码/过程/易于跟踪..等
另外,请记住,所有的functional函数都将在for循环后处理。在functional中,它可能会导致错误的“i”值。使用闭包:
字符串
你应该做的是知道什么时候它完成了是使用一个递归模式,就像dec(我认为)做。这是非常简单的,然后自己做。
型
这段代码可能无效,但你应该能够弄清楚如何做到这一点。
步骤库也很好(我想只有30行代码)
zengzsys4#
我不明白为什么client.smembers和client.get(Redis查找)需要回调而不是简单的语句-这让生活变得非常复杂。
是的,所以每个人都同意回调地狱是 no bueno。在撰写本文时,回调是Node的一个垂死的功能。不幸的是,Redis库没有对返回Promises的原生支持。
但是有一个模块你可以像这样要求:
第一个月
这是一个标准库,包含在Node运行时中,有一堆我们可以使用的实用函数,其中一个是“promisify”:https://nodejs.org/api/util.html#util_util_promisify_original
当然,当你七年前问这个问题时,util.promisify(original)并不存在,因为它是在-v 8.0.0中添加的,所以我们现在可以用更新的答案更新这个问题。
所以promisify是一个函数,我们可以传递给它一个像
client.get()
这样的函数,它将返回一个新的函数,该函数接受讨厌的回调行为,并将其 Package 得很好,很整洁,使其返回Promise。所以promisify接受任何接受回调作为最后一个参数的函数,并使其返回Promise,听起来这正是你七年前想要的行为,我们今天可以提供。
字符串
因此,我们将
.get()
函数的引用传递给util.promisify()
。这会获取你的函数,将其 Package 起来,这样它就不会实现一个回调,而是返回一个Promise。所以
util.promisify()
返回一个新的函数,这个函数已经被 promisified 了。所以你可以使用这个新函数并覆盖
client.get()
上现有的函数。现在,你不必使用回调来进行Redis查找。所以现在你可以像这样使用async/await
语法:const cachedMembers = await client.get('user:' + user_ids[i]);
个所以我们等待这个问题被解决,无论它解决了什么,都会被分配给
cachedMembers
。代码可以通过使用ES6数组帮助器方法而不是
for
循环来进一步清理以进行更新。我希望这个答案对当前用户有用,否则OP就过时了。