javascriptloopsobjectindefinite

Looping through a droste effect javascript Object


I have got comments within comments within comments in an Object (much like a droste effect). For every comment a certain action needs to be performed. The comments can go on indefinately. How should I loop though them?

E.g

Comments
    randcomment1
        text: "Not important"
        uid: 1234
        Comments
            randsubcomment1
                text: "again ni"
                uid: 5346
            randsubcomment2
                text: "ni"
                uid: 9087
    randcomment2
        text: "N.I"
        uid: 4567

I need to get the uid of every comment, use that to make a call to a database and then add a third key/value pair to a comment.

e.g

inidviualcomment
    text: "ni"
    uid: 4567
    nickname: "Mr example" <------ this one should be added based on the uid

What I currently have

//  using firebase and vuejs, not relevant
for (let key in val){
      db.ref("users/" + val[key].uid).once("value").then(function(snapshot){
        let value = snapshot.val()
        let nickName = value.nickname
        this.$set(val[key], "nickName", nickName)
      }.bind(this))
      // 
      // here you could add 
      // if (typeod val[key][Comments] != "undefined"){
      //     for (key in val[key][comments]){
      //        and so on, but this is not sustainable
      //    }
      // }
      //
    }

How should I loop through the comments, in such a way that it doesn't matter how many comments within comments there are?


Solution

  • You need a recursive function. Something like this should work:

    You could also make this functional and remove potential side-effects.

    /**
     * First function: get all uids
     * @param {array} uids
     * @param {object} comments
     * @returns {void}
     */
    function addUids(uids, comments) {
        comments.forEach(function(comment){
            if (uids.indexOf(comment.uid) === -1) {
                uids.push(comment.uid);
            }
            if (typeof comment.comments !== "undefined") {
                addUids(uids, comment.comments);
            }
        });
    }
    
    /**
     * Second function: transform comments storage and add nicknames
     * @param {object} nicknames
     * @param {object} comments
     * @returns {void}
     */
    function addNicknames(nicknames, comments) {
        comments.forEach(function(comment){
            comment.nickname = nicknames[comment.uid] || null;
            if (typeof comment.comments !== "undefined") {
                addNicknames(nicknames, comment.comments);
            }
        });
    }
    
    var uids = [];
    addUids(uids, allComments);
    
    // fetch nicknames - make some ajax call (fetch) and return something like:
    var nicknames = {"uid1": "nickname1", "uid2": "nickname2"};
    addNicknames(nicknames, allComments);
    

    (Sorry, i did not test the code, you will have to do that yourself, i think you will get the idea of the recursive function and i dont have so much time right now)