理解node.js中的promises for recursive function [英] Understanding promises in node.js for recursive function

查看:158
本文介绍了理解node.js中的promises 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 your getFromRedis 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. Use then 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 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 ));
      });
      

      这篇关于理解node.js中的promises for recursive function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆