Recursive asynchronous JavaScript for processing embedded data

I want to write a JavaScript function that 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. Each object contains one 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 each line of "value" on the console and pause for two seconds for each "delay" before processing the delay array in the same way. The function should support any nesting delay depth. The example of two-level delay of deep delays shown above is just an example.

( ):

a
b
c
d

?

+6
3

Promises async/wait:

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);
Hide result
+5

. values, : ["a", "delay", "b", "delay", "c", "d"]

, .

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);
  }
}
+2

Using async/ awaitand destroying objects, here's a more readable approach for recursively walking and printing an object:

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

function sleep(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms)
  })
}

async function walk(array) {
  for (const { value, delay } of array) {
    if (value) {
      console.log(value)
    } else if (delay) {
      await sleep(1000)
      await walk(delay)
    }
  }
}

walk(data)
Run codeHide result
+2
source

All Articles