Express.js能否分块发送响应?实测遇响应延迟显示问题
Express.js 分块发送响应数据的实现方法
Express.js 完全支持分块发送响应数据,你当前的代码没生效,主要是因为响应体缓冲未及时刷新,以及客户端对不完整JSON的渲染限制。以下是修正方案和说明:
问题分析
你代码里的res.flushHeaders()仅用于发送响应头,不会刷新响应体的缓冲。Express 默认会缓冲写入的数据,直到达到阈值或调用res.end()才会发送给客户端,导致浏览器和Postman要等完整响应才显示。
修正后的代码示例
const express = require('express'); const app = express(); const port = 3111; const sleep = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; app.get('/', async (req, res) => { // 明确启用分块传输(Express 也会自动识别,但手动设置更直观) res.setHeader('Transfer-Encoding', 'chunked'); res.setHeader('Content-Type', 'application/json'); // 发送JSON数组开头 res.write('['); // 立即刷新缓冲,让客户端接收第一块数据 res.flush(); for (let i = 1; i <= 10; i++) { // 改为10条数据方便测试 res.write(JSON.stringify(`data ${i}`)); if (i < 10) { res.write(','); } // 每次写入后强制刷新缓冲,确保数据实时发送 res.flush(); await sleep(500); } res.write(']'); res.end(); }); app.listen(port, () => { console.log(`App is live at http://localhost:${port}`); });
关键调整点
- 调用
res.flush():在每次res.write()后调用该方法(Express 4.16.0+支持),强制将缓冲中的数据发送给客户端,而不是等待缓冲满或响应结束。 - 分块传输头:虽然Express会自动在无
Content-Length头时添加Transfer-Encoding: chunked,手动设置能更明确地启用分块传输。
客户端实时处理的优化方案
由于浏览器对不完整JSON的渲染限制(会等待完整结构才显示),如果需要客户端实时处理每一块数据,建议改用JSON Lines格式(每行一个JSON对象):
服务端代码
app.get('/stream', async (req, res) => { res.setHeader('Content-Type', 'application/x-ndjson'); res.setHeader('Transfer-Encoding', 'chunked'); for (let i = 1; i <= 10; i++) { // 每行输出一个JSON对象,用换行分隔 res.write(JSON.stringify({ id: i, content: `data ${i}` }) + '\n'); res.flush(); await sleep(500); } res.end(); });
客户端处理代码
fetch('/stream') .then(res => { const reader = res.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; function processChunk() { reader.read().then(({ done, value }) => { if (done) return; buffer += decoder.decode(value); // 按换行分割数据行 const lines = buffer.split('\n'); buffer = lines.pop(); // 保留未完成的最后一行 // 逐行解析JSON并处理 lines.forEach(line => { if (line.trim()) { const data = JSON.parse(line); console.log('Received:', data); } }); processChunk(); }); } processChunk(); });
客户端工具的注意事项
- Postman:默认会等待响应完成才展示结果,需在请求设置中开启「实时响应(Real-time response)」来查看分块数据。
- Chrome:Network面板的「Response」标签可能不会实时更新,但「Raw」或「Preview」标签可以看到逐步接收的数据,也可以用上述客户端代码实时处理。
内容的提问来源于stack exchange,提问作者ar099968
相关产品推荐
相关产品推荐

