setImmediate()

时间:2017-10-15 08:38:40

标签: node.js recursion setimmediate

我有以下递归函数:

 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(),我会得到所有元素,并且当我使用{时出现相同的情况{1}}(我事先知道应该有多少元素)。我做错了什么,如何在这里正确实现这个功能(或模拟)?

这是应用蹦床前的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中的对象状态从未探测到探索更改。主要问题是两个函数vpreVisit(v)也改变了该对象的状态 - 第一次访问它的写入顺序和第二次(从先前的调用中弹出堆栈时) ) 分别。当我用蹦床转换postVisit(v)时,他们开始写出意想不到的错误结果。

以这种方式在另一个函数中调用该函数:

explore()

两个函数for (let i = 0; i < vNum; i++) { if (nodes[i].visited) continue; explore(i, cN); cN++; } postVisit

preVisit

1 个答案:

答案 0 :(得分:0)

假设我们有一个像这样的普通递归函数 - 这里的问题是我们有一个forEach循环,每次调用explore都可以产生0,1或更多对{{1}的额外调用 - 为了解决这个问题,我们需要一些方法对所有节点进行排序,这样我们就可以逐个处理它们而不会炸毁堆栈

explore

我们在const explore = node => { node.visited = true preVisit (node) Array.from (node.adjacencies) .filter (n => n.visited === false) .forEach (n => explore (n)) postVisit (node) } 函数内部引入了一个主循环,它处理节点的数组,而不仅仅是单个节点。当数组中有节点时,循环将继续运行。将对内部循环函数而不是外部explore函数进行递归调用。这种数组方法效果很好,因为每个节点都有一定数量的邻接 - 当可以轻松地将0,1或更多相邻节点添加到此列表时 - 还要注意添加了延续explore,这样我们就可以对postVisit以正确的顺序调用

最重要的是,对k的递归调用是在尾部位置 - 这使我们为下一次转换做好准备

loop

一旦我们有一个尾递归循环,我们就可以为堆栈安全递归引入const explore = node => { const loop = ([x, ...xs], k) => { if (x === undefined) k () else { x.visited = true preVisit (x) loop ( Array.from (x.adjacencies) .filter (n => n.visited === false) .concat (xs), () => (postVisit (x), k ()) ) } } return loop ([node], x => x) } / loop

recur