Search code examples
javascriptobjectrecursiondelaydelayed-execution

Iterate over an object with delay


I am trying to iterate over nested children of an object, but need have a delay after every child. Normally I would just write a recursive function and use that to iterate over an object, but this happens near instantly. How can I do this with a delay?

I thought about saving the index in a variable and accessing children using that, then increasing the index every time a setInterval is run, but how can this be expanded to take nesting into account?

Function to iterate:

function iter(obj) {
    for (var i = 0; i < obj.length; i++) {
        console.log(obj[i].command);
        if (typeof obj[i].contains == "object") {
            iter(obj[i].contains);
        }
    }
}
iter(object);

Example object:

[
    {
        "command":"do (5)",
        "contains":[
            {
                "command":"move.up()",
                "contains":false
            },
            {
                "command":"move.left()",
                "contains":false
            },
            {
                "command":"if (kind == \"item\")",
                "contains":[
                    {
                        "command":"move.down()",
                        "contains":false
                    }
                ]
            },
            {
                "command":"move.right()",
                "contains":false
            }
        ]
    }
]

Solution

  • First create a flat array from the hierarchy:

    function iter(obj) {
      var result = [];
      for (var i = 0; i < obj.length; i++) {
        result.push(obj[i]);
        if (typeof obj[i].contains == "object") {
          result = result.concat(iter(obj[i].contains));
        }
      }
      return result;
    }
    
    var items = iter(object);
    

    Now you can iterate the array with a timer and an index:

    var index = 0;
    var timer = window.setInterval(function(){
      if (index < items.length) {
        console.log(items[index].command);
        index++;
      } else {
        window.clearInterval(timer);
      }
    }, 1000);
    

    Demo:

    var object = [
        {
            "command":"do (5)",
            "contains":[
                {
                    "command":"move.up()",
                    "contains":false
                },
                {
                    "command":"move.left()",
                    "contains":false
                },
                {
                    "command":"if (kind == \"item\")",
                    "contains":[
                        {
                            "command":"move.down()",
                            "contains":false
                        }
                    ]
                },
                {
                    "command":"move.right()",
                    "contains":false
                }
            ]
        }
    ];
    
        function iter(obj) {
          var result = [];
          for (var i = 0; i < obj.length; i++) {
            result.push(obj[i]);
            if (typeof obj[i].contains == "object") {
              result = result.concat(iter(obj[i].contains));
            }
          }
          return result;
        }
    
        var items = iter(object);
    
        var index = 0;
        var timer = window.setInterval(function(){
          if (index < items.length) {
            log(items[index].command);
            index++;
          } else {
            window.clearInterval(timer);
          }
        }, 1000);
    
    function log(str) {
      document.getElementById('log').innerHTML += str + '<br>';
    }
    <div id="log"></div>