带有setTimeout的递归JS函数 [英] Recursive JS function with setTimeout
问题描述
我有以下代码
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
This output is not in order because of the setTimeout
问题:
- 如何更改它以输出如下图所示的内容?
- 如何知道此递归函数中的最后一次迭代?我需要在列表耗尽后运行。
我 cant 使用forEach因为我有使用setTimeouts的原因不同。我知道setTimeout在循环中不能正常工作。任何想法????
I cant use forEach because I have to use setTimeouts for a different reason. I understand setTimeout does not work properly in a loop. Any ideas????
期望输出:
推荐答案
一般来说,当你想进行广度优先迭代时,你需要使用一个队列(即FIFO)。 Javascript没有本机队列数据结构,所以这只是使用一个数组和 shift
,但它仍然可以完成工作。
Generally speaking when you want to do breadth-first iteration, you need to use a queue (ie. FIFO). Javascript doesn't have a native queue data structure, so this just uses an array and shift
, but it still gets the job done.
在这里,您只需将所有内容都推送到每个级别的队列中。这可以保证孩子们在父母之后被推进,因此你首先要对父母进行迭代。通常使用图表,您还可以跟踪您去过的地方,但由于这是一棵树,因此没有循环。
Here you just push everything into the queue at each level. This insures the children get pushed in after the parents, and therefore you iterate over the parents first. Normally with a graph you would also keep track of where you've been, but since this is a tree, there are no loops.
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);
编辑 - FOR DEPTH FIRST:
EDIT - FOR DEPTH FIRST:
如果你想要深度优先,你基本上使用堆栈而不是队列。这里有点奇怪,因为你关心孩子的顺序,所以我们向后加载堆栈。
If you want depth first you basically use a stack rather than a queue. Here it's a little strange because you care about the order of the children, so we load the stack backwards.
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(stack) {
let current = stack.pop()
if (current === undefined) return
console.log(current.id)
if(current.children) {
stack.push(...current.children.reverse())
}
setTimeout(function(){
recursive(stack)
})
}
recursive(data.reverse());
这篇关于带有setTimeout的递归JS函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!