使用Q递归生成具有多个子链的链

时间:2013-06-16 06:09:23

标签: node.js promise q

基本上,我正在尝试设置一个树,其中每个节点都有一个对它的父节点的引用。我尝试了以下内容:

function insert_node(node_data, parent_id) {
  var deferral = Q.defer()
  deferral.promise.then(async_create_node(node_data, parent_id))

  deferral.promise.then(function(parent_node_id) {
    var deferral = Q.defer()
    node_data.children.forEach(function(node) {
      deferral.promise.then(insert_node(generate_node_data(node), parent_node_id))
    }
    return deferral.resolve();
  }

  return deferral.resolve();
}

function insert_all_nodes() {
  var deferral = Q.defer();
  deferral.promise.then(insert_node(top_node));
  deferral.resolve()
}

问题是我需要它一次只创建一个节点,并等到该节点完成创建,然后才转到下一个节点。它现在的工作方式,它将在第一个节点完成之前开始创建一个新节点,这会导致问题。我已尝试以多种方式嵌套函数,并使用Q.fcall()。我需要async_create_node为多个子节点返回的id,否则我只使用递归。

1 个答案:

答案 0 :(得分:0)

异步性和递归的结合使得一个人的思维变得有点棘手。

首先,我们必须确保async_create_node()返回一个承诺,否则没有依据可以承认它的异步性,整个企业需要同步。

其次,让我们假设,在每个级别(特别是最高级别),我们不仅要知道已经创建了级别的节点,还要知道它下面的整个树已经被创建了

然后,您应该能够做到这样的事情:

function insert_node(node_data, parent_id) {
    var dfrd = Q.defer();
    async_create_node(node_data, parent_id).then(function(id) {
        var promises = [];
        node_data.children.forEach(function(node) {
            promises.push(insert_node(generate_node_data(node), id));
        });
        Q.all(promises).then(dfrd.resolve);
    });
    return dfrd.promise;
}

function insert_all_nodes() {
    return insert_node(top_node_data, top_node_id);
}

这一切都是我的头脑,未经测试。

修改

要按顺序创建兄弟节点,您可以在.then()循环中构建forEach链,如下所示:

function insert_node(node_data, parent_id) {
    var dfrd = Q.defer();
    async_create_node(node_data, parent_id).then(function(id) {
        var p = Q.defer().resolve().promise;//Seed promise on which to build a then() chain.
        node_data.children.forEach(function(node) {
            p = p.then(function() {
                insert_node(generate_node_data(node), id);
            });
        });
        p.then(dfrd.resolve);
    });
    return dfrd.promise;
}