2017-09-09 69 views
6

我正在寻找写JavaScript函数,其采用以下数据结构作为参数:递归异步JavaScript的

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

正如你可以看到,该数据结构是对象的数组。每个对象都包含一个属性。这些属性中的每一个都是带有字符串的“值”,或者是与其值相同类型的另一个数组的“延迟”。

函数应该在控制台上以相同的方式处理延迟数组之前,向控制台输出每个“值”字符串,并为每个“延迟”暂停两秒。该函数应该支持任何深度的延迟嵌套。上面显示的两级深度延迟嵌套仅仅是一个例子。

该函数的输出到控制台,例如上面的数据应该是(以这个顺序,也只有这个顺序):

a 
b 
c 
d 

一个人怎么会写来实现此功能的代码?

+0

SO不是代码写入服务;这是一个提出_specific_问题或寻求_specific_问题帮助的地方。请回顾[我如何提出一个好问题?](https://stackoverflow.com/help/how-to-ask) – Hamms

+0

这是一个关于具体问题的具体问题,即使用递归异步JavaScript处理嵌套数据结构和承诺。 – user2245766

+0

我没有看到问号,我确实看到“请编写代码以实现此功能”这一短语 – Hamms

回答

5

可以使用的承诺和异步/的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);

+0

c和d之间不应该有延迟吗? – Nick

+0

@heybignick我认为这个问题有点不清楚,但我认为你是对的。我编辑了我的anwser。 =) –

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

这是一个很好的主意来简化事情 – user2245766

+0

谢谢!它有效,但几乎不如Jose的解决方案雄辩。 – Nick

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)