2017-09-09 71 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)