节点中的递归函数内存不足 - 尝试了process.nextTick,但仍然失败

时间:2014-06-02 05:49:37

标签: node.js recursion

这是我得到的错误:

FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory

这是代码。注意我添加了process.nextTick以按照另一篇文章中的建议进行递归调用,但我仍然收到内存错误。

function req(url){
    return new Promise(function (resolve, reject) {
        request({
            url: url
        }, function (err, res, body) {
            if (err) {
                console.trace(err);
                return reject(err);
            } else if (res.statusCode !== 200) {
                err = new Error("Unexpected status code: " + res.statusCode);
                err.res = res;
                console.trace(err);
                return reject(err);
            }

            resolve(body);
        });
    });
}


function getNextUrl(url){
    var page = provider.results.page(url);

    nextPages.push(url);

    req(url)
        .then(function (body) {
            var $ = cheerio.load(body)
                , $profileUrls = provider.results.profileUrls($)
                , nextUrl = provider.results.next($, url);

            async.eachLimit($profileUrls, argv.concurrent, function(el, cb){
                var $el = $(el)
                    , profileUrl = provider.results.profileUrl($, $el);

                getProfileUrl(profileUrl, url)
                    .then(function(body){
                        cb(null);
                    }, function(err){
                        console.trace(err);
                    });
            }, function(err){
                if ( err ) {
                    return console.trace(err);
                }

                console.log('Done with profile urls.'.info);

                //here is the recursive call
                process.nextTick(function(){
                    getNextUrl(nextUrl);
                });
            });
        }, function(err){
            console.trace(err);
        });
}


getNextUrl(startUrl);

此代码运行正常,大约10k网址,但如果我将其提高到20k,我会收到此错误。我需要它能够超过20k,也许是200k的初学者。我希望这件事最终只能处理任何数字而不会崩溃。

async.eachLimit完成时,它会在新网址上调用自己。我怀疑这是问题的根源。我在一个对象数组中收集了一些数据,但是当我将这个JSON写入磁盘时,它只有大约5mb,而我的系统有1gb的ram。

1 个答案:

答案 0 :(得分:2)

为了将来参考,我对related issue的回复:

  

这应该与cheerio#263相关:URL是原始文档的片段,维护它们意味着将整个文档保留在内存中。在20k页之后,你将耗尽内存。修复方法是强制V8创建副本,例如。通过使用(“”+ url).substr(1)。