You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js使用fs.createWriteStream生成大文件出现JS堆内存溢出错误

问题原因分析

你对流的核心认知没有错误:Node.js流的设计目标确实是实现数据的分块处理,避免全量载入内存。本次内存溢出的核心原因是没有遵守可写流的背压(Backpressure)处理规则,属于流的错误使用方式。

具体触发逻辑

  • 可写流(fs.WriteStream)内部默认配置了大小为highWaterMark(默认16KB)的缓冲区,用于暂存待写入磁盘的数据
  • 调用write()方法时会返回布尔值:返回true说明当前写入的数据已经成功放进缓冲区,可继续写入;返回false说明缓冲区已经被占满,此时应该暂停写入操作,等待缓冲区数据全部写入磁盘、drain事件触发后再恢复写入
  • 你代码中的同步for循环完全忽略了write()的返回值,以远高于磁盘写入的速度持续生成字符串并调用write(),所有无法放入缓冲区的待写数据会被缓存到内存队列中,无法被垃圾回收,最终占满V8堆内存触发OOM错误。
修复后的代码示例
const fs = require('fs');
const file = fs.createWriteStream('./big.file');

async function writeBigFile() {
  let i = 0;
  const max = 1e8;
  async function write() {
    let ok = true;
    while (i < max && ok) {
      const chunk = `lorem ipsum ${i}`;
      i++;
      if (i === max) {
        // 最后一次写入后调用end
        file.end(chunk);
      } else {
        // 缓冲区没满就继续写,满了就退出循环等drain
        ok = file.write(chunk);
      }
    }
    if (i < max) {
      // 缓冲区满了,等drain触发后再继续写
      await new Promise(resolve => file.once('drain', resolve));
      await write();
    }
  }
  await write();
}

writeBigFile().catch(console.error);

上述代码会在缓冲区占满时自动暂停写入,等待磁盘写完缓冲区内容后再恢复生成新数据,内存占用会稳定在极低的水平,不会出现溢出问题。


内容的提问来源于stack exchange,提问作者Ibnjunaid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 02:15:02