用于嵌套数据结构处理的递归异步JavaScript

时间:2017-09-09 00:26:25

标签: javascript asynchronous promise

我希望编写一个JavaScript函数,它将以下数据结构作为参数:

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

如您所见,数据结构是一个对象数组。每个对象都包含一个属性。这些属性中的每一个都是"值"用字符串或"延迟"与另一个与其值相同类型的数组。

该功能应该打印到控制台每个"值"字符串和每个"延迟"暂停两秒钟在以相同方式处理延迟阵列之前。该函数应支持任何深度的延迟嵌套。上面显示的两级深度延迟嵌套只是一个例子。

上述示例数据的控制台功能输出应该是(按此顺序,只有这个顺序):

a
b
c
d

如何编写代码来实现此功能?

3 个答案:

答案 0 :(得分:5)

您可以使用Promises和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);




答案 1 :(得分:2)

这是一个想法。你最终得到的是values数组看起来像 ["a", "delay", "b", "delay", "c", "d"]

另外,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);
  }
}

答案 2 :(得分:2)

使用async / await和对象解构,这是一种更具可读性的递归步行和打印对象的方法:



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)