2017-09-09 27 views
6

Tôi đang tìm để viết một hàm JavaScript trong đó có cấu trúc dữ liệu sau đây là một cuộc tranh cãi:JavaScript không đồng bộ đệ quy để chế biến cấu trúc dữ liệu lồng nhau

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

Như bạn có thể thấy, các cấu trúc dữ liệu là một mảng của các đối tượng . Mỗi đối tượng chứa một thuộc tính duy nhất. Mỗi thuộc tính này là "giá trị" với chuỗi hoặc "độ trễ" với một mảng khác có cùng loại với giá trị của nó.

Chức năng sẽ in ra bàn điều khiển từng chuỗi "giá trị" và tạm dừng trong hai giây cho mỗi "độ trễ" trước khi xử lý mảng trễ theo cùng một cách. Hàm sẽ hỗ trợ bất kỳ độ sâu làm tổ trễ nào. Độ trễ sâu hai cấp được lồng ở trên chỉ là một ví dụ.

Đầu ra của chức năng để giao diện điều khiển cho các dữ liệu ví dụ trên nên (theo thứ tự này, và chỉ có thứ tự này):

a 
b 
c 
d 

Làm thế nào người ta sẽ viết code để thực hiện chức năng này?

+0

SO không phải là dịch vụ viết mã; đó là một nơi để đặt câu hỏi _specific_ hoặc nhận trợ giúp về vấn đề _specific_. Vui lòng xem lại [Làm cách nào để đặt câu hỏi hay?] (Https://stackoverflow.com/help/how-to-ask) – Hamms

+0

Đây là câu hỏi cụ thể về một vấn đề cụ thể, cụ thể là xử lý cấu trúc dữ liệu lồng nhau với JavaScript không đồng bộ đệ quy và hứa hẹn. – user2245766

+0

Tôi không thấy dấu chấm hỏi và tôi thấy cụm từ "Hãy viết mã để thực hiện chức năng này" – Hamms

Trả lời

5

Bạn có thể sử dụng Promises và async/chờ:

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

Không nên có sự chậm trễ giữa c và d? – Nick

+0

@heybignick Tôi nghĩ rằng đó là một chút không rõ ràng trong câu hỏi, nhưng tôi nghĩ rằng bạn đang phải. Tôi đã chỉnh sửa anwser của tôi. =) –

2

Đây là một ý tưởng. Những gì bạn sẽ kết thúc là một mảng values trông giống như ["a", "delay", "b", "delay", "c", "d"]

Ngoài ra, 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

đây là một ý tưởng tuyệt vời để đơn giản hóa mọi thứ – user2245766

+0

Cảm ơn! Nó hoạt động, nhưng gần như không hùng biện như giải pháp của Jose. – Nick

2

Sử dụng async/await và đối tượng destructuring, đây là một cách tiếp cận dễ đọc hơn cho đệ quy đi bộ và in các đối tượng:

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)

Các vấn đề liên quan