NodeJS:内存使用增长在recursion刮擦直到崩溃

我在NodeJS中从GET URL API中获取了一堆东西。 我正在循环着一年中的几个城市。 我有一个scrapeChunk()函数,我为每个参数实例调用一次,即{startDate:…,endDate:…,location:…}。 里面我做一个jsdomparsing一个表,转换为CSV,将CSV附加到一个文件。 在所有的嵌套asynchronouscallback中,我终于再次用下一个参数实例调用scrapeChunk函数。

这一切工作,但节点实例增长,并在RAM中增长,直到我得到一个“致命错误:CALL_AND_RETRY_2分配失败 – 进程内存不足”错误。

我的问题:我做错了什么,或者这是JavaScript和/或我正在使用的库的限制吗? 我可以以任何方式完成每个任务,释放它的内存,然后开始下一个任务? 我尝试了FuturesJS的一个序列,似乎也遭受同样的泄漏。

可能发生的情况是,你正在构build一个非常深的调用树,并且上层的引用树保持引用他们的数据,所以它永远不会被垃圾回收器声明。

有一件事是在你自己的代码中,当你最后调用一个callback函数时,通过调用process.nextTick()来做到这一点。 这样,调用函数可以结束并释放它的variables。 另外,确保你没有把所有的数据堆积到一个全局的结构中,以保持这些引用的永久性。

在没有看到代码的情况下,想出好的答案是有点棘手的。 但是,这不是node.js或其方法的限制(有很多使用它的长时间运行和复杂的应用程序),而是如何使用它。

你可能想尝试cheerio而不是JSDom。 作者声称它更精简,速度更快8倍。

假设你的描述是正确的,我认为问题的原因是显而易见的 – recursion调用scrapeChunk()。 使用循环(或查看节点的stream设施)分派任务,并确保它们实际返回。

这里发生了什么事情听起来像这样:

 var list = [1, 2, 3, 4, ... ]; function scrapeCheck(index) { // allocate variables, do work, etc, etc scrapeCheck(index+1) } 

在足够长的列表中,根据你在函数体中所做的事情,保证会耗尽内存,堆栈深度或堆,或者任何数量的东西。 我build议的是这样的:

 var list = [1, 2, 3, 4, ... ]; list.forEach(function scrapeCheck(index) { // allocate variables, do work, etc, etc return; }); 

令人沮丧的嵌套callback是一个正交的问题,但我build议你看一下asynchronous库(尤其是asynchronous/瀑布 ),这对于这类任务来说是stream行和有用的。