【问题标题】:How to avoid memory leaks with the use of Node Streams and promises如何使用 Node Streams 和 Promise 避免内存泄漏
【发布时间】:2021-09-09 08:41:33
【问题描述】:

我尝试将节点流包装在异步函数中。但我想知道以下代码是否泄漏内存。承诺解决(拒绝)后,readStreamresult 会被垃圾回收吗?如果没有,我应该如何避免内存泄漏?

async function readFile(path, keyword) {
  const readStream = fs.createReadStream(path, {encoding: 'utf8'});
  let result = await getCachedResult(); // getCachedResult is another async function
  return new Promise((resolve, reject) => {
    readStream.on('data', (chunk) => {
      if (chunk.includes(keyword)) {
         result += chunk;
      }
    })
    readStream.on('error', (err) => {
        reject(err)
        readStream.close()
    })
    readStream.on('end', () => {
        resolve(result)
        readStream.close()
    })
  })
}

【问题讨论】:

  • 仅供参考,此代码 if (chunk.includes(keyword)) 存在问题,因为块边界可以位于数据中的任何位置,包括关键字中间的任何位置。
  • @jfriend00 谢谢。代码 sn-p 是我的代码的简化版本。实际上,我使用 Readline 模块一次读取一行。
  • 请不要以这种基本方式简化。请在以后的所有问题上发布您的真实代码。由于某些未知的原因,人们认为他们应该在此处发布伪代码或简化/简化代码,这通常会阻止我们理解真正的问题或提出最佳解决方案。您在询问垃圾收集,然后没有显示您的真实代码。没有人能真正回答你的真实代码,因为你没有展示它,事实上,你还涉及其他可能影响垃圾收集的模块。

标签: javascript node.js promise memory-leaks node-streams


【解决方案1】:

当前的 JavaScript 内存垃圾回收算法基于删除 代码中无法访问的数据对象和值(包括包含函数变量和参数的环境记录对象)

那么,async function readFile 正文中的哪些数据对象和值它返回一个 Promise 对象之后是可访问的?

返回后不会保留对 pathkeyword 的引用,因此它们有资格进行 GC。

readStreamresultresolverejectchunkerr 的引用仅由处理在流上注册的流事件的匿名函数持有。

可以从readStream 实例对象(或其事件发射器)访问处理函数。

readStream 对象负责删除对无法再进行的回调的引用:无论是在 end 事件本身之后,还是在调用 readStrem.close 之后。无论哪种方式,您都无需担心使用 Promise 或读取流会造成内存泄漏。

【讨论】:

  • 完美解释:对象不是在promise结算时进行垃圾回收,而是在流关闭并进行垃圾回收时。
猜你喜欢
  • 1970-01-01
  • 2013-09-23
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
相关资源
最近更新 更多