使用JS Stream API将Node.js流数据传到React前端无法实时输出如何解决
问题原因及修改方案
后端修改(server.js)
- 补全响应头配置,禁用所有环节的缓冲,新增
Connection: keep-alive和反代缓冲禁用标识 - 启动Python进程时添加
-u参数,强制关闭Python的标准输出缓冲,避免Python层缓存输出内容 - 禁用当前路由的压缩中间件(如果你的Node服务用了express的compression等压缩插件)
修改后的代码:
// 先禁用当前路由的压缩逻辑 firmwareRouter.get('/run_test', (req, res, next) => { // 强制不使用压缩,避免压缩中间件缓存数据 req.headers['accept-encoding'] = 'identity'; next(); }, (req, res) => { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', // 禁用nginx等反向代理的缓冲 'X-Accel-Buffering': 'no' }); const pathToExample = '/server/path/to/test.py'; const { spawn } = require('child_process'); // 加-u参数开启Python无缓冲模式 const pythonProcess = spawn('python', ['-u', pathToExample]); pythonProcess.stdout.on('data', (data) => { res.write(data); }); pythonProcess.on('close', (code) => { res.end('Process has ended'); }); });
前端修改(Firmware.js)
- 删除GET请求中无意义的
Content-Type请求头,该字段仅用于标识请求体格式,GET请求无请求体不需要设置 - TextDecoder解码时添加
stream: true配置,避免跨数据块的字符缓存 - 状态更新改为追加逻辑,避免每次覆盖之前的输出内容
修改后的版本1参考代码:
import { useState, Fragment } from 'react'; export default function Firmware(props) { const [data, setData] = useState(''); async function runTest() { try { const url = 'api/firmware/run_test' const request = { method: 'GET', headers: {} } const res = await fetch(url, request); const reader = res.body.getReader(); const decoder = new TextDecoder('utf-8'); let done, value; while (!done) { ({ value, done } = await reader.read()); if (done) break; const chunk = decoder.decode(value, { stream: true }); console.log(chunk); // 追加数据而不是覆盖 setData(prev => prev + chunk); } } catch (err) { console.log('frontend:Firmware', err); } } return ( <Fragment> <pre>{data}</pre> <button onClick={() => runTest()}>Run Test </button> </Fragment > ) }
开发环境代理配置修改
如果你在本地用了webpack-dev-server、vite等前端开发服务的反向代理,需要关闭代理的缓冲配置:
- webpack代理配置新增:
buffer: false, proxyTimeout: 0 - vite代理配置新增:
proxy: { '/api': { target: '你的后端地址', buffer: false, proxyTimeout: 0 } }
验证方法
你可以先直接用curl请求后端接口curl http://你的后端地址/api/firmware/run_test,如果curl能实时输出内容,说明后端逻辑正常,问题出在前端或者代理层;如果curl也不能实时输出,优先排查后端配置。
内容的提问来源于stack exchange,提问作者Glenn Oberlander
相关产品推荐
相关产品推荐

