Node.js中res.write()传输流数据块无响应问题排查
问题原因与解决方案:res.write()无效且返回false
核心原因
你代码里的致命问题是在ReadableStream的data事件触发前就调用了res.end()。res.end()会立刻终止HTTP响应、关闭连接,后续的res.write()根本没机会把数据发送给客户端。
至于res.write()返回false,这是Node.js的正常机制:当响应缓冲区被写满时,res.write()会返回false,表示当前不能继续写入,需要等待缓冲区排空(触发drain事件)后再继续。但在你的场景里,这个返回值只是次要现象,真正导致数据发不出去的是提前调用了res.end()。
修正方案
有两种可靠的修正方式,推荐第二种更简洁的写法:
方式1:手动管理流事件
修改代码,把res.end()移到文件流的end事件回调里,同时处理缓冲区满的情况:
import { createServer } from 'http' import { createReadStream } from 'fs' const server = createServer((req, res) => { if (req.method === 'GET' && req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }) const readStream = createReadStream('./src/public/index.html', { encoding: 'utf8' }) readStream.on('data', (chunk) => { console.log(chunk) const canWrite = res.write(chunk) // 缓冲区满时暂停读取,避免内存溢出 if (!canWrite) { readStream.pause() res.once('drain', () => { readStream.resume() }) } }) // 文件流读取完毕后再结束响应 readStream.on('end', () => { res.end() }) // 处理文件读取错误 readStream.on('error', (err) => { res.writeHead(500) res.end('服务器错误') console.error(err) }) } }) const PORT = 3000 || 8080 server.listen(PORT, () => { console.log(server.address()) })
方式2:使用pipe()自动管理(推荐)
Node.js的流提供了pipe()方法,可以自动处理流的传输、缓冲区控制和响应结束,代码更简洁不易出错:
import { createServer } from 'http' import { createReadStream } from 'fs' const server = createServer((req, res) => { if (req.method === 'GET' && req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }) // 直接将文件流管道到响应对象 createReadStream('./src/public/index.html', { encoding: 'utf8' }) .pipe(res) .on('error', (err) => { res.writeHead(500) res.end('服务器错误') console.error(err) }) } }) const PORT = 3000 || 8080 server.listen(PORT, () => { console.log(server.address()) })
pipe()会自动帮你做这些事:
- 当响应缓冲区满时暂停读取文件
- 缓冲区排空后恢复读取
- 文件流结束时自动调用
res.end() - 处理流传输中的错误
内容的提问来源于stack exchange,提问作者anathrax
相关产品推荐
相关产品推荐

