递归承诺创建树

时间:2017-04-25 04:08:59

标签: javascript asynchronous recursion promise

当apin传递给它时,树api会返回子节点。

我首先传递根节点,然后根据返回的节点,如果它们的 hasChildren 参数为true,则递归返回所有节点。

有没有办法知道函数何时完成了树的创建。

function recursivelyFetchChildren(id, selectedAsset, parentId){
    return ajaxCall(id, selectedAsset, parentId)
    .then(function(data){
        //collects all childs in childs array
        childs.push(data);
        for(var i=0; i<data.length; i++){
            if(data[i].HasChildren){
                return recursivelyFetchChildren(id,selectedAsset,data[i].Id);
            }else{
                //this return statement prematurely completes the promise
                return data[i];
            }
        }
    });
}

recursivelyFetchChildren(id, selectedAsset, parentId).then(function(){
    print(childs)  //prints the childs before all the promises have resolved
});

有人可以提出一种方法,我可以让recursivelyFetchChildren函数等待渲染完整的树吗?

1 个答案:

答案 0 :(得分:2)

走另一条路,并返回一个在解决了所有子节点后解析的函数。

{
  id: "123",
  data: {
    children: [
      { id: "234", value: 2, data: { children: [] } },
    ]
  }
}


const loadData = node => getData(`/url/${node.id}`).then(data => {
  return loadChildren(data.hasChildren ? data.children : [])
    .then(children => {
      data.children = children;
      node.data = data;
      return node;
    });
});
const loadChildren = children => Promise.all(children.map(loadData));

因为我正在返回并链接承诺,我返回的最外面的一个将无法解决,直到最内层的一个完成。

就个人而言,我可能会构建一个新节点,而不是修改我所拥有的节点,但这完全不同。

修改

相互递归:两个相互调用的函数。

function a () { return b(); }
function b () { return a(); }

如果你有一个树,其中每个根都有一个子数组,那么你可以编写两个函数来在另一个之间来回反弹:一个用于处理节点,一个用于处理节点数组。当然还有其他一些例子,但是其中一个是你想要的递归函数,另一个是循环,或者让你一次调用递归函数的东西......通常;再次,还有其他情况。

const tree = {
  value: 1,
  children: [{
    value: 2,
    children: []
  }, {
    value: 3,
    children: []
  }]
};

const sumChildren = children =>
  children
    .map(sumNode)
    .reduce((x, y) => x + y, 0);

const sumNode = node =>
  node.value + sumChildren(node.children);

const total = sumNode(tree); // 6

承诺解决方案

在承诺方面,通常错过的一件事就是你可以在.then内回复承诺,并使承诺的解决等待更长时间。当它结算时,它将具有b解析的值(或b具有的错误)

eventuallyGetA()
  .then(a => eventuallyGetB(a.data))
  .then(b => console.log(`I waited for ${b}`));

您甚至可以执行类似

的操作
const wait = ms =>
  new Promise(resolve => setTimeout(resolve, ms));

doX()
  .then(() => wait(2000))
  .then(doY)
  .then(() => wait(3000))
  .then(doZ);

关于该序列将要做什么应该非常简单。

希望有所帮助。