Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recursive asynchronous JavaScript for nested data structure processing

I'm looking to write a JavaScript function which takes the following data structure as an argument:

let data = [
  {value: 'a'},
  {delay: [
    {value: 'b'},
    {delay: [
      {value: 'c'}
    ]}
  ]},
  {value: 'd'}
];

As you can see, the data structure is an array of objects. The objects each contain a single property. Each of these properties is either a "value" with a string or a "delay" with another array of the same type as its value.

The function should print to the console each "value" string and pause for two seconds for each "delay" before processing the array of the delay in the same manner. The function should support any depth of delay nesting. The two level deep delay nesting shown above is just an example.

The output of the function to the console for the example data above should be (in this order, and only this order):

a
b
c
d

How would one write the code to implement this function?

like image 891
user2245766 Avatar asked Sep 09 '17 00:09

user2245766


2 Answers

You can use Promises and async/await:

let data = [
  {value: 'a'},
  {delay: [
    {value: 'b'},
    {delay: [
      {value: 'c'}
    ]}
  ]},
  {value: 'd'}
];

const delay = () => new Promise( res => 
  setTimeout( res, 2000) ) 

const recFn = async data =>{
  for(let obj of data){
    if(obj.value){
      console.log(obj.value)
    } else if(obj.delay){
      await delay();
      await recFn(obj.delay)
    }
  }
}

recFn(data);
like image 154
Jose Hermosilla Rodrigo Avatar answered Nov 14 '22 18:11

Jose Hermosilla Rodrigo


Here's an idea. What you'll end up with is a values array that will look like ["a", "delay", "b", "delay", "c", "d"]

Also, here's a working fiddle.

let data = [
    {value: 'a'},
    {delay: [
      {value: 'b'},
      {delay: [
        {value: 'c'}
      ]}
    ]},
    {value: 'd'}
  ];

let values = [];

while(data.length) {
  if(typeof data[0].value !== 'undefined') {
    values.push(data[0].value);
    data.shift();
  }else {
    values.push('delay');
    var delayArray = data[0].delay; 
    data.shift();
    data = delayArray.concat(data);
  }
};

outputDelay(values);

function outputDelay(elements) {
    if(!elements.length) return false;
    if(elements[0] == "delay") {
    setTimeout(function(){
      elements.shift();
      outputDelay(elements);
    }, 2000);  
  } else {
    console.log(elements[0]);
    elements.shift();
    outputDelay(elements);
  }
}
like image 2
Nick Avatar answered Nov 14 '22 18:11

Nick