Javascript 理解node.js中递归函数的承诺

Javascript 理解node.js中递归函数的承诺,javascript,node.js,recursion,promise,Javascript,Node.js,Recursion,Promise,我尝试使用递归调用从redis中获取数据,在成员返回null时停止并返回 因此,我的数据是这样添加的: SADD parents.<name> <parent1> <parent2> SADD parents.<parent1> <grandparent1> <grandparent2> ... 我可以看看这些例子,从理论上看它应该如何工作,但我不能确定它应该如何与q实现一起工作。任何帮助都将不胜感激。 在与承诺打交道时,

我尝试使用递归调用从redis中获取数据,在成员返回null时停止并返回

因此,我的数据是这样添加的:

SADD parents.<name> <parent1> <parent2>
SADD parents.<parent1> <grandparent1> <grandparent2>
...
我可以看看这些例子,从理论上看它应该如何工作,但我不能确定它应该如何与q实现一起工作。任何帮助都将不胜感激。

  • 在与承诺打交道时,尽量保持纯洁。避免使用有副作用的函数,即操作其自身范围之外的任何变量
  • 避免将回调传递给函数。只将它们传递给promise方法。您可以使用
    r\u client.smembers()
    和调用
    getFromRedis
    方法来执行此操作
我只能看到一个特定的错误,它会使您的脚本无法工作:

return [];
不受回调的任何影响。因此,在这种情况下,
ret
永远不会得到解决。您将执行
ret.resolve([]);返回如果有。但是,有更好的解决方案可以让您再次使用
return

要重新构造脚本,有两点:

  • 使用(等)避免直接处理回调样式的API。使用
    then
    转换其结果,然后同步返回树叶或保证后代获得计算
  • 首先使用,然后转换其结果。不要向每个
    依赖项添加处理程序,而是在一个步骤中获得整个结果并构建
    构造


你以前有基于回调的解决方案吗?没有。我试过,但它更复杂。更简洁。当我看到它像这样工作时,这一切都是有道理的。出于某种原因,当我从命令行运行它时,它从不返回任何输出?这就像是陷入了一个循环。添加一些日志,看看你在这段时间里得到了什么,也许真的有。我不太了解redis,可能是因为我没有正确地从值构造查询-请参阅代码部分,您可能需要对其进行调整。似乎它应该可以工作,但我在q.js中发现了一个错误:
TypeError:Object在exports.commands.forEach.RedisClient.(匿名函数)在Promise.Promise.apply中没有方法“sendCommand”。(/Users/username/node\u modules/node redis/index.js:408:12)(~/node\u modules/q/q.js:752:41)at Promise.dispatch(~/node\u modules/q/q.js:1337:14)at flush(~/node\u modules/q/q.js:108:17)at process.startup.processNextTick.process.\u tickCallback(node.js:244:9)
我做过的一件事(无论哪种方式我都会得到错误):smembers从Redis取回缓冲区而不是字符串。因此我调用了“par”上的toString()。哦,找到了。我将Q.nfcall()更改为:
return Q.ninvoke(r_client,“smembers”,“parents.”+nodeName)。然后(函数(val){
为了解决这个问题,我三天的大部分时间都在拼命工作。非常感谢你的帮助。
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 ))} );
return [];
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 ));
});