如何在React中渲染Node.js返回的多个输出以展示视频转码进度
问题根因
你的现有代码逻辑存在明显的时序错误:res.end() 是同步执行的,而 hbjs.spawn 的 progress 事件是异步触发的,不等进度事件回调执行,HTTP响应就已经被关闭,自然拿不到任何返回值,这个问题和是否改用EJS没有任何关联。
可行实现方案
方案1:SSE(服务器推送事件,推荐)
适合单向下发进度的场景,轻量无需额外依赖,前端原生支持。
后端改造代码
app.get('/transcode-progress', (req, res) => { // 设置SSE响应头 res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); const transcodeTask = hbjs.spawn({ input: '你的输入文件路径', output: '你的输出文件路径' }) .on('progress', progress => { // SSE消息格式要求前缀 data: ,后缀\n\n res.write(`data: ${progress.percentComplete}\n\n`); }) .on('end', () => { // 转码完成后关闭响应 res.write(`data: 100\n\n`); res.end(); }) .on('error', err => { // 错误处理 res.write(`data: error:${err.message}\n\n`); res.end(); }); // 客户端断开连接时清理转码任务,避免资源泄漏 req.on('close', () => { transcodeTask.kill(); }); });
前端React代码
import { useState, useEffect } from 'react'; function TranscodePage() { const [progress, setProgress] = useState(0); useEffect(() => { const eventSource = new EventSource('/transcode-progress'); eventSource.onmessage = (event) => { const data = event.data; if (data.startsWith('error:')) { console.error('转码出错:', data.slice(6)); eventSource.close(); return; } const currentProgress = Number(data); setProgress(currentProgress); if (currentProgress >= 100) { eventSource.close(); // 转码完成后续逻辑 } }; eventSource.onerror = () => { eventSource.close(); }; return () => { eventSource.close(); }; }, []); return <div>转码进度:{progress}%</div>; }
方案2:WebSocket(适合需要双向交互的场景)
如果你的应用后续还有其他实时交互需求,可以用Socket.io实现:
- 后端监听客户端的转码请求,启动转码任务后,每次触发progress事件就向对应客户端发送进度消息
- 前端WebSocket连接成功后发起转码请求,监听进度消息更新状态即可
方案3:轮询(实现最简单,适合小型项目)
- 后端新增两个接口:一个是启动转码接口,返回唯一的任务ID,同时将任务进度存在内存/Redis中
- 另一个是进度查询接口,接收任务ID返回当前进度
- 前端拿到任务ID后,每隔300-500ms调用一次查询接口拉取进度,进度到100或报错后停止轮询
内容的提问来源于stack exchange,提问作者user14261498
相关产品推荐
相关产品推荐

