使用JavaScript递归创建树

时间:2018-06-21 06:08:40

标签: javascript

我想使用递归函数创建树。该函数的输入是一个节点,我想使用该递归函数向其添加子节点。

以下代码将更好地解释我的问题:

function getUpstreamChildrenRecusrively(node) {
  var receiverId = localStorage.getItem("ReceiverId");
    //API call to get the children node
    axios({
      method: 'get',
      url: window.location.origin+"/api/rwa/coverageView/getUpstreamChildren?id="+node.elementId,
      headers: {
        "ReceiverId":receiverId
      }
    })
      .then(response => {        
        localStorage.setItem("ReceiverId",response.headers["receiverid"]);
        var data = response.data;                                      
        for(var i = 0; i < data.length; i++) {
          var obj = data[i];                  
          var result = {};                                                
          result.text = obj.print;  
          result.elementId =  obj.id;
          result.elementText = obj.text; 
          result.expanded = true;
          result.visible = true; 
          result.icon = window.location.origin+"/api"+obj.image;        
          getUpstreamChildrenRecusrively(result);                       
          
          node.nodes = []; //nodes property will contain children
          node.nodes.push(result); 
          console.log("Tree so far:"+JSON.stringify(node));
        }                                     
      })    
    .catch(error => {      
    })         
}

对于每个递归调用,该节点的值都是一个单独的节点,在节点属性中具有单个子节点。我希望最终将节点与所有子节点一起成长。

此代码中我缺少什么?

提前谢谢!

2 个答案:

答案 0 :(得分:0)

您对递归的工作方式的理解是有缺陷的,我并不是无礼的,只是试图帮助您了解您需要进一步研究该主题。

  1. 首先,您不会从函数中返回任何内容
  2. 您还需要递归调用函数(执行异步调用,并以当前函数调用为范围)之后检查node的值。
  3. 您正在进行递归api调用,但未检查该函数何时停止执行。这意味着它将一直运行到您的api调用失败为止。

    function getUpstreamChildrenRecusrively(node) {
        var receiverId = localStorage.getItem("ReceiverId");
        //Api call to get the children node
        return axios({
            method: "get",
            url:
            window.location.origin +
            "/api/rwa/coverageView/getUpstreamChildren?id=" +
            node.elementId,
            headers: {
            ReceiverId: receiverId
            }
        })
        .then(response => {
            localStorage.setItem("ReceiverId", response.headers["receiverid"]);
            var data = response.data;
            for (var i = 0; i < data.length; i++) {
                var obj = data[i];
                var result = {};
                result.text = obj.print;
                result.elementId = obj.id;
                result.elementText = obj.text;
                result.expanded = true;
                result.visible = true;
                result.icon = window.location.origin + "/api" + obj.image;

                node.nodes = getUpstreamChildrenRecusrively(result); //nodes property will contain children
                console.log("Tree so far:" + JSON.stringify(node));
                return node;
            }
        })
        .catch(error => {
            /* I am using ES6 here, you can use something equavelant to check if node has a value */
            if (Object.keys(node).length > 0) {
                return node;
            } else {
                /* obviously you need other error handling logic here too */
            }
        });
    }

答案 1 :(得分:0)

您似乎希望getUpstreamChildrenRecusrively能够同步工作。详细了解javascript async / await和Promises。

这应该是怎么工作的

async function getUpstreamChildrenRecusrively(node) {
  const receiverId = localStorage.getItem("ReceiverId")

  const response = await axios({
    method: 'get',
    url: window.location.origin+"/api/rwa/coverageView/getUpstreamChildren?id="+node.elementId,
    headers: {
      ReceiverId: receiverId
    }
  })

  localStorage.setItem("ReceiverId",response.headers["receiverid"])
  const data = response.data

  node.nodes = node.nodes || []

  for(let i = 0; i < data.length; i++) {
    const obj = data[i]
    const result = {}
    result.text = obj.print
    result.elementId =  obj.id
    result.elementText = obj.text
    result.expanded = true
    result.visible = true 
    result.icon = window.location.origin + "/api" + obj.image
    node.nodes.push(result)
    await getUpstreamChildrenRecusrively(result)               
  }                                     
}

getUpstreamChildrenRecusrively(initialNode).then(() => {
  console.log('result node', initialNode)
})