Nodejs中关于jsdom内存泄漏,应该注意的问题

Nodejs中关于jsdom内存泄漏,应该注意的问题

在我开发的网站 爱比物价跟踪时,使用nodejs用于数据抓取,其中用到的解析页面的插件有jsdom, jquery, 刚开始数据量不是很大的时候,抓取没有遇到任何的问题,后来,需要抓取的页面很多(万级别以上),程序就开始包内存溢出, 之后,去google找答案,说是jquery的问题,没有办法我就把jquery去掉了,但是跑了一会,发现还是报统一的错误,最后发现是jsdom的问题, 就是说在使用完dom的时候,没有回收相应的垃圾信息,所以需要,我们自己在调用jsdom.env使用完dom后,调用一下window.close,只要gc就可以收集垃圾内存

大家可以在执行node 加入–trace_gc 看 一下内存清理,就一目了然


6 回复

Nodejs中关于jsdom内存泄漏,应该注意的问题

在我开发的网站 爱比物价跟踪 时,使用 Node.js 进行数据抓取。在这个过程中,我用到了一些解析页面的插件,比如 jsdom 和 jQuery。刚开始的时候,由于数据量不是很大,抓取过程一切正常。然而,当需要抓取的页面数量增加到万级别以上时,程序开始出现内存溢出的问题。

最初,我怀疑是 jQuery 的问题,于是将其移除。但即使如此,问题依然存在。最终我发现,真正的罪魁祸首是 jsdom。具体来说,在使用 jsdom 解析页面并生成 DOM 结构后,如果没有正确地释放这些资源,就会导致内存泄漏。

如何解决 jsdom 内存泄漏问题

为了防止 jsdom 引起的内存泄漏,我们需要确保在使用完 DOM 后正确地关闭窗口并释放资源。这可以通过调用 window.close() 方法来实现。下面是一个简单的示例代码:

const jsdom = require("jsdom");
const { JSDOM } = jsdom;

// 示例HTML字符串
const htmlString = `
<!DOCTYPE html>
<html>
<head>
    <title>Example Page</title>
</head>
<body>
    <h1>Hello, World!</h1>
</body>
</html>
`;

// 使用JSDOM解析HTML
const dom = new JSDOM(htmlString);

// 获取window对象
const window = dom.window;

// 在这里进行DOM操作...

// 使用完DOM后,调用window.close()来释放资源
window.close();

如何调试内存泄漏

如果你想要进一步调试内存泄漏问题,可以运行 Node.js 并启用垃圾回收日志。通过传递 --trace_gc 参数,你可以查看详细的垃圾回收信息,从而更好地理解内存是如何被管理的。

node --trace_gc your_script.js

通过这种方式,你可以观察到每次垃圾回收的过程,并确认是否有内存被正确地释放。如果发现某些对象仍然占用大量内存,那么可能需要进一步检查代码中是否存在未被正确处理的资源引用。

总结起来,使用 jsdom 时,确保在使用完 DOM 后调用 window.close() 方法来释放资源是非常重要的。这样可以有效避免内存泄漏问题,特别是在处理大量数据时。


jsdom 说爱它不容易~

说的没错,不过注意这个问题,使用jsdom还是不错的,至少暂时还没有遇到其他的问题

我使用了window.close 还是不行,还是会报: FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory

现在没问题了

在使用 Node.js 进行数据抓取时,如果你使用了 jsdom 来解析 HTML 页面,可能会遇到内存泄漏的问题。这通常是由于在使用完 DOM 对象后没有正确地清理资源导致的。

示例代码

const jsdom = require("jsdom");
const { JSDOM } = jsdom;

function parseHTML(html) {
    const dom = new JSDOM(html);
    const window = dom.window;
    
    // 在这里进行你的DOM操作
    // 例如:
    // console.log(window.document.querySelector('body').innerText);

    // 使用完DOM后,手动清理
    window.close();
}

// 示例HTML内容
const htmlContent = '<html><body><div>Hello World</div></body></html>';

// 解析HTML并清理DOM
parseHTML(htmlContent);

解释

  1. 初始化 JSDOM:

    const dom = new JSDOM(html);
    

    创建一个新的 JSDOM 实例,并传递给它一个 HTML 字符串。

  2. 获取 Window 对象:

    const window = dom.window;
    

    获取当前 JSDOM 实例的窗口对象。

  3. DOM 操作: 在这里你可以进行任何你需要的 DOM 操作,例如查询元素、修改内容等。

  4. 手动清理:

    window.close();
    

    在完成所有的 DOM 操作后,务必调用 window.close() 方法来清理窗口及其关联的 DOM 对象。这有助于避免内存泄漏问题。

使用 --trace_gc 调试内存

为了更好地理解内存管理和垃圾回收的情况,可以使用 Node.js 的 --trace_gc 参数启动你的 Node.js 应用程序。这样可以查看垃圾回收的日志,帮助你诊断内存泄漏问题。

node --trace_gc yourscript.js

通过这种方式,你可以更清楚地看到内存是如何被分配和回收的,从而更好地管理你的应用程序中的内存使用。

回到顶部