title: Recursively add property to every node in a tree-like structure and return modified tree
body: <p>I have the following data structure for a tree of comments in a thread. This structure is contained inside a single object.</p>
  
  <pre><code>comment {
      id: 1,
      text: 'foo',
      children: [
          comment {
              id: 2,
              text: 'foo-child',
              children: []
          },
          comment {
              id: 3,
              text: 'foo-child-2',
              children: []
          }
      ]
  },
  comment {
      id: 4,
      text: 'bar',
      children: []
  }
  </code></pre>
  
  <p>This is provided by a back-end API, there's no problem in that. What I want to do is recursively explore this tree and for each node (either root or child node) I want to perform an API call and get some extra data <strong>for every single node</strong>, slap in some extra properties, and return the entire tree with the new keys added to each node.</p>
  
  <pre><code>function expandVoteData(comments) {
      return new Promise((resolve, reject) =&gt; {
          let isAuth = Auth.isUserAuthenticated();
          // 'this' is the vote collection
          async.each(comments, (root, callback) =&gt; {
              // First get the vote data
              async.parallel({
                  votedata: function(callback) {
                      axios.get('/api/comment/'+root.id+'/votes').then(votedata =&gt; {
                          callback(null, votedata.data);
                      });
                  },
                  uservote: function(callback) {
                      if(!isAuth) {
                          callback(null, undefined);
                      } else {
                          axios.get('/api/votes/comment/'+root.id+'/'+Auth.getToken(), { headers: Auth.getApiAuthHeader() }).then(uservote =&gt; {
                              callback(null, uservote.data); // Continue
                          });
                      }
                  }
              }, function(error, data) {
                  if(error) {
                      console.log('Error! ', error);
                  } else {
                      // We got the uservote and the votedata for this root comment, now expand the object
                      root.canVote = isAuth;
                      root.totalVotes = data.votedata.total;
                      root.instance = 'comment';
  
                      if(data.uservote !== undefined) {
                          root.userVote = data.uservote;
                      }
  
                      if(root.children &amp;&amp; root.children.length &gt; 0) {
                          // Call this function again on this set of children
                          // How to "wrap up" this result into the current tree?
                          expandVoteData(root.children);
                      }
                      callback(); // Mark this iteration as complete
                  }
              });
          }, () =&gt; {
              // Done iterating
              console.log(comments);
              resolve();
          });
      })
  }
  </code></pre>
  
  <p>What it does is: accept a 'comments' parameter (which is the entire tree object), create a promise, iterate through each leaf node, and perform the respective API calls in asynchronous requests. If the leaf node has any children, repeat the function with each child node.</p>
  
  <p>This theoretically would work perfectly in a synchronous world, but what I do need to do is to get the new tree after every node has been processed for further processing, as a single object, just like it was as an input. In fact, I get multiple console prints for each individual node in the tree, evidencing that the code works as it's written... I don't want individual prints though, I want to wrap up the entire set of results in a single object. Ideally, the function should be called like this:</p>
  
  <pre><code>expandVoteData(comments).then(expanded =&gt; {
      // yay!
  });
  </code></pre>
  
  <p>Any tips on how to perform this? Thank you beforehand.</p>