我使用的是 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?或者是因为它在引擎盖下使用了生成器,并且返回将生成器标记为已完成,因此可以丢弃堆栈?
最佳答案
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);
}
在这个例子中,函数被返回,因此垃圾收集器可以安全地清理方法中声明的变量。请注意,堆栈会保留下来,如果此递归函数迭代次数过多,则会抛出超出最大调用堆栈大小
错误,但声明的变量位于堆中,因此可以在保持堆栈信息完整。
关于Node.js:异步函数中的尾部调用是否有优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49165805/