理解node.js中的promises for recursive function [英] Understanding promises in node.js for recursive function
问题描述
我正在尝试使用递归调用从redis中获取数据,当成员返回null时停止并返回。
I'm trying to use recursive calls to get data out of redis, stopping and returning when the members return null.
所以我的数据添加如下:
So my data is added like this:
SADD parents.<name> <parent1> <parent2>
SADD parents.<parent1> <grandparent1> <grandparent2>
...
最终数据应如下所示:
[
{
label: <name>,
parents: [
{ label: <parent1>,
parents: [ {label: <grandparent1>}, {label: <grandparent2> }] },
{ label: <parent2> }
]
}
]
这是我的代码混乱(从不同的来源拼凑而成),但我不知道我在做什么。不确定这段代码是否有用,我可能会偏离轨道。
Here's the code I'm messing with (sort of cobbled together from different sources), but I have no idea what I'm doing. Not sure if this code is even useful, I could be way off track.
var redis = require('node-redis');
var r_client = redis.createClient();
var Q = require('q');
function getFromRedis(nodeName){
var ret = Q.defer();
r_client.smembers('parents.' + nodeName,function(err,val){
if (err) ret.reject(err);
else {
var constructedObject={}; //this is our returned object
var dependents=[];
if (val)
{
for (var k in val){ //iterate the keys in val
constructedObject.name = val[k];
dependents.push(getFromRedis(val[k])
.then(function(subVal){
constructedObject[k]=subVal;
return ret.promise;
})
);
}
}
else { return [] }
}
Q.all(dependents)
.then(function(){ret.resolve(constructedObject);},ret.reject.bind(ret));
});
return ret;
}
getFromRedis( 'greg', function(out) {console.log('Final output: ' + JSON.stringify( out ))} );
我可以看看这些例子,从理论上看它应该如何工作,但我无法得到我的想法是如何使用q实现。任何帮助将不胜感激。
I can look at the examples and see theoretically how it's supposed to work, but I can't get my mind around how it should work with the q implementation. Any help would be greatly appreciated.
推荐答案
- 尝试在使用时尽可能保持纯洁承诺。避免使用具有副作用的函数,即操作超出其自身范围的任何变量。
- 避免将回调传递给函数。只传递给promise方法。您正在使用
r_client.smembers()
以及调用getFromRedis
方法时执行此操作 - Try to be as pure as you can when working with promises. Avoid functions that have side effects, i.e. do manipulate any variables outside of their own scope.
- Avoid passing callbacks to functions. Do only pass them to promise methods. You are doing this both with
r_client.smembers()
and when invoking yourgetFromRedis
method
我只能看到一个特定的错误,会阻止你的脚本工作:
I can see only one specific mistake that would keep your script from working:
return [];
对回调没有任何影响。因此,在这种情况下永远不会解决 ret
。你会做 ret.resolve([]);返回;
如果有的话。但是,有更好的解决方案可让您再次使用 return
。
does not have any effect from the callback. So, ret
is never going to be resolved in this case. You would do ret.resolve([]); return;
if at all. However, there are better solutions that let you use return
again.
要重构脚本,有两点:
- 使用
Q.nfcall
辅助函数(等),以避免直接处理回调式API。然后使用然后
转换其结果 - 同步返回树叶或后代获取计算的承诺。 - 使用
Q.all
,然后转换其结果。不要为每个依赖
添加处理程序,而是获取整个结果并在一个步骤中构建构造
。
- Use the
Q.nfcall
helper function (and the like) to avoid dealing with callback-style APIs directly. Usethen
to transform its result then - synchronously returning the tree leaves or a promise for the descendant-getting computations. - Use
Q.all
first, and then transform its result. Don't add a handler to eachdependent
, but get the whole result and build theconstruct
in one single step.
function getFromRedis(nodeName){
return Q.ninvoke(r_client, "smembers", 'parents.' + nodeName).then(function(val) {
// this is our returned object
var constructedObject = {label: nodeName};
if (val) {
var dependents = val.map(function(par) {
// get a promise for the next level
return getFromRedis(nodeName+"."+par.toString());
});
return Q.all(dependents).then(function(dependentResults) {
constructedObject.parents = dependentResults;
return constructedObject;
});
} else {
return constructedObject; // without parents
}
});
}
getFromRedis( 'greg' ).done(function(out) {
console.log('Final output: ' + JSON.stringify( out ));
});
这篇关于理解node.js中的promises for recursive function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!