Node.js:异步函数中的尾调用是否有优化?

时间:2018-03-08 05:07:50

标签: node.js recursion tail-recursion

我正在使用Node v8.10.0

上述问题解释了Node.js如何不再支持TCO。我最近遇到过像这样的函数的问题:

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    await processBatch(nthBatch + 1);
}

代码有内存泄漏,通过将其更改为:

立即修复
async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    return processBatch(nthBatch + 1);
}

我对实际工作感到惊讶,因为在上述问题中,它清楚地解释了Node 8.x中不支持TCO。那么有什么特别的东西可以在这里实现TCO吗?或者是因为它在发动机罩下使用发电机并且返回标记发电机完成,所以堆栈可以丢弃?

1 个答案:

答案 0 :(得分:2)

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    await processBatch(nthBatch + 1);
}

此代码段导致内存泄漏,因为在注释中声明的变量无法进行垃圾回收,因为解释器不知道它们将不再需要。例如解释器当时不知道await之后没有可能需要所有声明变量的行。

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    return processBatch(nthBatch + 1);
}

在此示例中,返回函数,因此垃圾收集器可以安全地清理方法中声明的变量。请注意,堆栈会粘在一起,如果此递归函数有太多迭代,则会抛出Maximum call stack size exceeded错误,但变量会在堆中生效,因此可以在保持堆栈信息不变的情况下进行垃圾回收。 / p>