带有setTimeout的递归JS函数

我有以下代码

var data = [ { id: "0" }, { id: "1", children: [ { id: "1.1", children: [ { id: "1.1.1", children: [ { id: "1.1.1.1", children: [ { id: "1.1.1.1.1" }, { id: "1.1.1.1.2" }, { id: "1.1.1.1.3" } ] }, { id: "1.1.1.2" }, { id: "1.1.1.3" } ] }, { id: "1.1.2" }, { id: "1.1.3" }, ] }, { id: "1.2" }, { id: "1.3" } ] }, { id: "2" }, { id: "3" } ]; function recursive(current) { var first = current[0]; current.shift(); var remaining = current; console.log(first.id); if (first.children) { setTimeout(function(){ recursive(first.children); }) } if (remaining.length) { setTimeout(function(){ recursive (remaining); }); } } recursive(data); 

由于setTimeout,此输出不按顺序排列

在此处输入图像描述

题:

  1. 如何更改它以输出如下图所示的内容?
  2. 我怎么知道这个递归函数的最后一次迭代? 列表耗尽后我需要运行一些东西。

不能使用forEach因为我必须使用setTimeouts的原因不同。 据我所知,setTimeout在循环中无法正常工作。 有任何想法吗????

期望的输出:

在此处输入图像描述

一般来说,当你想进行广度优先迭代时,你需要使用一个队列(即FIFO)。 Javascript没有本机队列数据结构,所以这只是使用数组和shift ,但它仍然可以完成工作。

在这里,您只需将所有内容都推入每个级别的队列中。 这可以保证孩子们在父母之后被推进,因此你首先要对父母进行迭代。 通常使用图表,您还可以跟踪您去过的地方,但由于这是一棵树,因此没有循环。

 var data = [ { id: "0" }, { id: "1", children: [ { id: "1.1", children: [ { id: "1.1.1", children: [ { id: "1.1.1.1", children: [ { id: "1.1.1.1.1" }, { id: "1.1.1.1.2" }, { id: "1.1.1.1.3" } ] }, { id: "1.1.1.2" }, { id: "1.1.1.3" } ] }, { id: "1.1.2" }, { id: "1.1.3" }, ] }, { id: "1.2" }, { id: "1.3" } ] }, { id: "2" }, { id: "3" } ]; function recursive(queue) { var current = queue.shift(); if (current === undefined) return console.log(current.id) if (current.children) { current.children.forEach(node => { queue.push(node) }) } setTimeout(function() { recursive(queue) }) } recursive(data); 

纠结的电线

递归和异步是单独的概念,但我们没有理由不能一起使用它们。 首先,我们将看一些同步遍历,然后添加对异步的支持。 我喜欢这种答案,因为我们可以看到以多种方式表示的相同程序。 我们专注于产生重大影响的变化。

我们从使用发电机的一种方法开始 –

 const Empty = Symbol () const breadthFirst = function* ([ node = Empty, ...nodes ]) { if (node === Empty) return else (yield node, yield* breadthFirst (nodes.concat (node.children || []))) } const data = [{ id: "0" },{id: "1",children: [{id: "1.1",children: [{id: "1.1.1",children: [{id: "1.1.1.1",children: [{ id: "1.1.1.1.1" },{ id: "1.1.1.1.2" },{ id: "1.1.1.1.3" }]},{ id: "1.1.1.2" },{ id: "1.1.1.3" }]},{ id: "1.1.2" },{ id: "1.1.3" },]},{ id: "1.2" },{ id: "1.3" }]},{ id: "2" },{ id: "3" }] for (const x of breadthFirst (data)) console.log (x.id) // 0 1 2 3 1.1 1.2 1.3 1.1.1 ... 1.1.1.1.3