Understanding promises in node.js for recursive function
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>
...
And the final data should look like:
[
{
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 ))} );
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.
r_client.smembers()
and when invoking your getFromRedis
method I can see only one specific mistake that would keep your script from working:
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;
ret.resolve([]); return;
if at all. However, there are better solutions that let you use return
again.
To restructure your script, there are two points:
Q.nfcall
helper function (and the like) to avoid dealing with callback-style APIs directly. Use then
to transform its result then - synchronously returning the tree leaves or a promise for the descendant-getting computations. Q.all
first, and then transform its result. Don't add a handler to each dependent
, but get the whole result and build the construct
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 ));
});
链接地址: http://www.djcxy.com/p/16000.html
上一篇: AngularJS和AdSense
下一篇: 理解node.js中递归函数的承诺