Stream 与背压是什么?为什么不能把大文件全部读进内存?
先理解原理和示例,再练习完整口述与追问。
回答要点
分块消费;Readable/Writable/Transform;速度差导致缓冲;write false 等 drain;pipeline 统一错误与关闭。
原理拆解
流让数据边产生边处理,不必等全部内容进入内存。上游快、下游慢时,若一直写入,待处理缓冲会不断增大;背压让下游告知上游暂停或减速。Writable.write 返回 false 表示应等 drain 后再继续,不表示本次内容没被接收,也不应因此把同一块再写一次。highWaterMark 是调节缓冲的门槛,不是所有场景的硬内存上限。
示例与推演
const { pipeline } = require('stream/promises')
const { createReadStream, createWriteStream } = require('fs')
const { createGzip } = require('zlib')
async function compress(input, output) {
await pipeline(createReadStream(input), createGzip(), createWriteStream(output))
}
Node16 可使用这里的 pipeline Promise API。链路按消费速度推进,失败时抛错并处理流生命周期;实际任务还应处理部分输出文件、取消与权限。
易错点
pipe 不等于所有错误自动完整处理。HTTP 下载链路失败后响应可能已发送,不能再无条件返回一段 JSON 错误体。
参考回答可直接练习口述
Stream 通过分块与背压协调生产和消费,适合大文件、代理与压缩。我优先使用 pipeline 组合链路,尊重 write/drain,限制缓冲并处理取消、错误和不完整产物,而不是 readFile 整个大文件。Node Stream 文档