簡體   English   中英

遞歸承諾創建樹

[英]Recursive promises to create tree

當將node元素傳遞給樹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函數等待呈現完整樹的方法嗎?

另一種方法是,在解析所有子級后返回一個已解析的函數。

{
  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);

關於該序列將要執行的操作應該非常簡單。

希望能有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM