防止Javascript函数因内存太多而耗尽内存

时间:2013-09-07 01:21:35

标签: javascript performance node.js memory

我正在nodeJS中构建一个使用requestcheerio解析DOM的网络抓取工具。当我使用node时,我认为这更像是一个普遍的javascript问题。

tl; dr - 创建~60,000 - 100,000个对象,耗尽我所有计算机的RAM,在节点中出现out of memory错误。

以下是刮刀的工作原理。它是循环中的循环,我从来没有设计过这么复杂的东西,所以可能有更好的方法来做到这一点。

循环1:在数组中创建名为“sitesArr”的10个对象。每个对象代表一个要刮的网站。

var sitesArr = [
    {
        name: 'store name',
        baseURL: 'www.basedomain.com',
        categoryFunct: '(function(){ // do stuff })();',
        gender: 'mens', 
        currency: 'USD',
        title_selector: 'h1',
        description_selector: 'p.description'
    },
    // ... x10
]

循环2:循环遍历'sitesArr'。对于每个站点,它通过“请求”进入主页并获取类别链接列表,通常为30-70个URL。将这些URL附加到它们所属的当前“sitesArr”对象中,名称为“categories”的数组属性。

var sitesArr = [
    {
        name: 'store name',
        baseURL: 'www.basedomain.com',
        categoryFunct: '(function(){ // do stuff })();',
        gender: 'mens', 
        currency: 'USD',
        title_selector: 'h1',
        description_selector: 'p.description',
        categories: [
                        {
                            name: 'shoes',
                            url: 'www.basedomain.com/shoes'
                        },{
                            name: 'socks',
                            url: 'www.basedomain.com/socks'
                        } // x 50
                    ]
    },
    // ... x10
]

循环3:循环浏览每个“类别”。对于每个URL,它获取产品链接列表并将它们放入数组中。通常每类约300-1000种产品

var sitesArr = [
    {
        name: 'store name',
        baseURL: 'www.basedomain.com',
        categoryFunct: '(function(){ // do stuff })();',
        gender: 'mens', 
        currency: 'USD',
        title_selector: 'h1',
        description_selector: 'p.description',
        categories: [
                        {
                            name: 'shoes',
                            url: 'www.basedomain.com/shoes',
                            products: [
                                'www.basedomain.com/shoes/product1.html',
                                'www.basedomain.com/shoes/product2.html',
                                'www.basedomain.com/shoes/product3.html',
                                // x 300
                            ]
                        },// x 50
                    ]
    },
    // ... x10
]

循环4:循环浏览每个“产品”数组,转到每个网址并为每个网址创建一个对象。

var product = {
    infoLink: "www.basedomain.com/shoes/product1.html",
    description: "This is a description for the object",
    title: "Product 1",
    Category: "Shoes",
    imgs: ['http://foo.com/img.jpg','http://foo.com/img2.jpg','http://foo.com/img3.jpg'],
    price: 60,
    currency: 'USD'
}

然后,对于每个产品对象,我将它们发送到MongoDB函数,该函数在我的数据库中执行upsert

问题

这一切都很好,直到这个过程变得很大。每次运行此脚本时,我都会创建大约60,000个产品对象,过了一会儿,我的所有计算机的RAM都用完了。更重要的是,在我的流程中途完成后,我在Node中收到以下错误:

 FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory

我非常关注这是一个代码设计问题。一旦我完成了它们,我应该“删除”它们吗?解决这个问题的最佳方法是什么?

0 个答案:

没有答案