【问题标题】:Recursive Async Looping in NodeJSNodeJS 中的递归异步循环
【发布时间】:2015-03-14 12:00:45
【问题描述】:

我正在尝试执行递归异步循环,以从 nodejs 中的第三方库跟踪特定对象的所有子对象。

伪代码如下:

var tracer = function(nodes){
  var promises [];

  nodes.forEach(function(node){

    // trace returns a promise ...
    var promise = builder.trace(node)
    promises.push(promise);

    promise.then(function(tree){

      // if we had children, get those
      if(tree.children.length){
        promises.push.apply(promises, tracer(tree.children));
      }
    });   

  });

  return promises;
};

RSVP.all(tracer(myArr)).then(function(allTrees){ ... });

但我不知道如何让它们全部正确解析并在一个数组中返回结果。

【问题讨论】:

  • tracer(myArr) 怎么会有.then?在此代码中,您不会返回使用 .then 的承诺。

标签: javascript node.js recursion promise


【解决方案1】:

你不能push延迟回调中数组上的递归承诺。相反,您需要立即推送一个代表递归结果的 Promise(通过那些延迟生成的 Promise 解决)。幸运的是,您甚至可以从 then 电话中得到准确的回复。

此外,我会将each 换成map,并在函数内部立即执行RSVP.all,因为我不希望调用者处理这个问题。

function tracer(nodes){
  var promises = nodes.map(function(node){
    // trace returns a promise ...
    var promise = builder.trace(node)
    var recusivePromise = promise.then(function(tree){
      // if we had children, get those
      if (tree.children.length)
        return tracer(tree.children));
      else
        return node;// the leaf node itself
    });
    return recusivePromise; // which will resolve with the `tracer(…)` result
                            // or the leaf
  });
  return RSVP.all(promises);
}

tracer(myArr).then(function(allTrees){ … });

【讨论】:

  • 注意:这将返回列表列表与平面数组。
  • @amcdnl:是的,它应该匹配树结构。如果你想要一个平面数组,让每个recursivePromise 解析为一个数组(通过返回单例数组中的叶子),并在.all() 之后添加一个concat 步骤。
  • @DanKanze:这是基本的函数式编程:-)
【解决方案2】:

我最终采用了计数器类型的方法......

var traceDeps = function(parents, cb){
  var count = 0, 
    trees = [], 
    trace = function(nodes){
      nodes.forEach(function(node){
        count++;
        builder.trace(node).then(function(tree){
          trees.push(tree);

          if(tree.children.length){
            trace(tree.children);
          }

          count--;
          if (count === 0) cb(trees);
        });
      });
    };

  trace(parents);
};

traceDeps(myArr, function(trees){ ... });

【讨论】:

  • 为什么这么复杂?当您可以使用 Promise 时,无需使用回调和计数器。您也忽略了这种方法的错误。
  • 如果任何 trace() 承诺被拒绝,您不会注意到(而是无限期地等待您从未调用过的回调)
  • 此解决方案不如 Bergi 的解决方案,并且忽略错误。你应该考虑改用他的。
  • 是的,我同意。感谢@Bergi 的帖子
猜你喜欢
  • 2013-07-11
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 2015-06-09
  • 2014-05-21
  • 1970-01-01
相关资源
最近更新 更多