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

我试图使用递归调用来从redis获取数据,当成员返回null时停止并返回。

所以我的数据是这样添加的:

SADD parents.<name> <parent1> <parent2>
SADD parents.<parent1> <grandparent1> <grandparent2>
...

最终的数据应该如下所示:

[
 {
     label: <name>,
     parents: [
         { label: <parent1>,
           parents: [ {label: <grandparent1>}, {label: <grandparent2> }] },
         { label: <parent2> }
     ]
 }
]

这是我弄乱的代码(来自不同来源的拼凑在一起),但我不知道我在做什么。 不知道这段代码是否有用,我可能会偏离轨道。

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实现一起工作。 任何帮助将不胜感激。


  • 尝试使用承诺时尽可能地纯粹。 避免有副作用的功能,即操作任何超出其范围的变量。
  • 避免将回调传递给函数。 只能通过它们来承诺方法。 你正在用r_client.smembers()和调用你的getFromRedis方法来做到这一点
  • 我只能看到一个让您的脚本无法工作的特定错误:

    return [];
    

    从回调没有任何影响。 所以,在这种情况下ret永远不会被解决。 你会做ret.resolve([]); return; ret.resolve([]); return; 如果有的话。 但是,有更好的解决方案可以让您再次使用return

    重构你的脚本,有两点:

  • 使用Q.nfcall帮助函数(等)来避免直接处理回调式API。 then使用它来转换它的结果,然后同步返回树叶或承担后代获得计算。
  • 首先使用Q.all ,然后转换结果。 不要为每个dependent项添加一个处理程序,而是获取整个结果并在一个步骤中构建construct
  • 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/15999.html

    上一篇: Understanding promises in node.js for recursive function

    下一篇: How to get current attributed string in non