Node.js中Readable stream在Express.js内用pipe返回响应失效求解
Node.js 流发送数据问题修复方案
核心问题原因
你写的自定义可读流没有标记数据传输结束,且不符合流的按需拉取设计逻辑,导致流卡住、响应无法正常结束。
具体问题点
- 所有数据
push完成后没有执行stream.push(null),这是可读流标记数据全部传输完成的必要操作,缺少这行的话end事件永远不会触发,pipe方法也不知道流已经传输完成,会一直挂起响应。 - 传入Readable构造函数的
read方法为空实现,虽然这不是直接导致报错的原因,但提前把所有数据全量推入流内部缓冲区的写法会丢失流分批处理、控制内存占用的优势,数据量大时还会导致内存溢出。
修复后代码
更推荐的pipe版本(符合流设计规范)
const { Readable } = require("stream") app.get('/test', (req,res) => { const month = ['jan','feb','mar','apr','may','jun','jul']; let dataIndex = 0 const stream = new Readable({ read(size) { // 所有数据读取完成,标记流结束 if (dataIndex >= month.length) { this.push(null) return } // 按需推送数据 this.push(month[dataIndex], 'utf8') dataIndex++ } }); stream.setEncoding('utf8') stream.pipe(res) })
兼容你原有写法的修复版本
如果你坚持要提前把所有数据推入缓冲区,只需要补加标记流结束的代码即可:
const { Readable } = require("stream") app.get('/test', (req, res) => { const month = ['jan','feb','mar','apr','may','jun','jul']; const stream = new Readable({read(size){}}); stream.setEncoding('utf8') for (let m of month) { stream.push(m) } // 新增这行,标记可读流没有更多数据 stream.push(null) stream.on('data', (data) => { console.log(data) res.write(data,'utf8') }) stream.on('end',() => { res.end(); }) })
额外说明
你的原代码中路由函数加了async关键字但没有用到异步逻辑,不会影响运行,不需要的话可以删除避免不必要的误解。
内容的提问来源于stack exchange,提问作者abhimanyu
相关产品推荐
相关产品推荐

