【发布时间】:2018-03-26 23:12:17
【问题描述】:
我有以下递归函数:
function explore(v, componentN) {
return function () {
nodes[v].visited = true;
nodes[v].componentNumber = componentN;
preVisit(v);
adjList[v].forEach((item) => {
if (!nodes[item].visited){
ex(item, componentN)
}
});
postVisit(v);
return nodes;
}
}
function ex(item, com){
trampoline(function () {
return explore(item, com)
})
}
function trampoline(fn) {
while(fn && typeof fn === 'function') {
fn = fn()
}
}
我想使用setImmediate() 以避免堆栈溢出问题(它应该以这种方式实现,而不是在迭代方法中)。然而,当我执行这个函数时,我只得到数组res,只有第一个元素,而如果我不使用setImmediate(),我会得到所有元素,当我使用nextTick()时会出现同样的情况(我事先知道应该有多少元素)。我做错了什么,如何在此处正确实现此功能(或模拟)?
这是应用蹦床之前的explore()函数
function explore(v, componentN) {
nodes[v].visited = true;
nodes[v].componentNumber = componentN;
preVisit(v);
adjList[v].forEach((item) => {
if (!nodes[item].visited){
explore(item, componentN)
}
});
postVisit(v);
return nodes;
}
它接受两个参数:v 是 nodes 数组中应该探索的元素的索引,componentN 只是图中组件的计数器。 explore() 不返回任何内容,它只是将数组 nodes 中 v 键下对象的状态从未探索更改为已探索。主要问题是preVisit(v) 和postVisit(v) 两个函数也改变了该对象的状态——分别写入第一次和第二次访问它的顺序(从先前的调用弹出堆栈时)。当我用蹦床转换explore()时,他们开始写出意想不到的错误结果。
该函数正在以这种方式在另一个函数中被调用:
for (let i = 0; i < vNum; i++) {
if (nodes[i].visited) continue;
explore(i, cN);
cN++;
}
还有两个函数postVisit和preVisit
function preVisit(v){
nodes[v].preVisit = visitCounter;
visitCounter++;
}
function postVisit(v) {
nodes[v].postVisit = visitCounter;
visitCounter++;
}
【问题讨论】:
-
不要不使用
setImmediate来避免堆栈溢出 - 详情请参阅my answer -
@naomik,感谢您的回答,我已阅读并尝试实现蹦床。所以它确实起作用了,堆栈溢出问题消失了,但又出现了另一个问题。我在这个问题中使用图形,我在递归函数体中有两个函数调用,即
write()。添加蹦床后,他们写了错误的信息,我得到了意想不到的结果。你能告诉我如何解决这个问题吗? -
粘贴您的更新尝试
-
@naomik,感谢您的回答,我刚刚将最初问题中的代码从抽象变为真实。所以我遇到了
preVisit()和postVisit()函数的问题,与我不使用蹦床的情况相比,它们写错了后序。我试图将它们包装在setInterval()中,但没有任何成功。
标签: node.js recursion setimmediate