前端接收流式数据的完整方案(SSE/WebSocket/Fetch API)_前端sse
一、流式数据
什么是流式数据?
- 数据分多次传输,无需等待完整内容即可开始处理
- 典型场景:实时日志、股票行情、AI生成内容(如ChatGPT逐字输出)
二、5种主流实现方案
1. Server-Sent Events (SSE)
特点:
- 单向通信(服务端→客户端)
- 基于HTTP协议,自动重连
- 兼容性:除IE外主流浏览器均支持
代码示例:
const eventSource = new EventSource(\'/api/stream\');// 接收消息eventSource.onmessage = (event) => { console.log(\'New data:\', event.data);};// 自定义事件类型eventSource.addEventListener(\'stockUpdate\', (e) => { const data = JSON.parse(e.data); updateStockChart(data);});// 错误处理eventSource.onerror = () => { console.error(\'Stream failed\');};
服务端要求:
Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive
2. WebSocket
特点:
- 全双工通信
- 适合高频双向数据交换
代码示例:
const socket = new WebSocket(\'wss://api.example.com/stream\');socket.onopen = () => { socket.send(\'subscribe:stocks\'); // 发送初始指令};socket.onmessage = (event) => { const data = JSON.parse(event.data); renderRealTimeData(data);};socket.onclose = () => { console.log(\'Disconnected\');};
协议对比:
3. Fetch API + Streams API
特点:
- 精细控制数据流
- 适合处理大文件下载
代码示例:
const response = await fetch(\'/api/large-file\');const reader = response.body.getReader();while (true) { const { done, value } = await reader.read(); if (done) break; // 处理分块数据(Uint8Array) const text = new TextDecoder().decode(value); console.log(\'Chunk:\', text);}
应用场景:
- 逐行读取CSV文件
- 视频流处理
4. XMLHttpRequest (旧式方案)
兼容性方案:
const xhr = new XMLHttpRequest();xhr.open(\'GET\', \'/api/stream\');xhr.onprogress = (event) => { const newData = xhr.responseText.substr(lastIndex); processData(newData);};xhr.send();
5. Web Workers + Stream(CPU密集型处理)
优化方案:
// 主线程const worker = new Worker(\'stream-worker.js\');worker.postMessage({ cmd: \'start\', url: \'/api/stream\' });// worker.jsself.onmessage = async (e) => { const response = await fetch(e.data.url); const reader = response.body.getReader(); while (true) { const { done, value } = await reader.read(); self.postMessage({ data: value }); if (done) break; }};
三、关键问题解决方案
-
数据完整性
- 使用分隔符(如
\\n\\n
) - 实现ACK确认机制(WebSocket)
- 使用分隔符(如
-
性能优化
// 防抖处理高频数据let buffer = [];const debounceRender = _.debounce(() => { render(buffer); buffer = [];}, 100);socket.onmessage = (event) => { buffer.push(event.data); debounceRender();};
3.错误恢复
// SSE自动重连eventSource.onerror = () => { setTimeout(() => new EventSource(url), 5000);};
四、现代框架集成
React示例(SSE + Hook)
function useStream(url) { const [data, setData] = useState(\'\'); useEffect(() => { const es = new EventSource(url); es.onmessage = (e) => { setData(prev => prev + e.data); }; return () => es.close(); }, [url]); return data;}// 使用const logs = useStream(\'/api/log-stream\');
Vue示例(WebSocket)
export default { data() { return { stockData: [] } }, created() { this.socket = new WebSocket(\'wss://stocks.com\'); this.socket.onmessage = (e) => { this.stockData.push(JSON.parse(e.data)); }; }, beforeUnmount() { this.socket.close(); }}
五、调试工具
-
Chrome DevTools:
- Network面板查看SSE/WS连接
- 流数据实时监控
-
测试工具:
# 模拟SSE服务printf \"data: test1\\n\\n\" | nc -l 8080
六、服务端配合要求
text/event-stream
data: {...}\\n\\n
Upgrade: websocket
Transfer-Encoding: chunked
上面这些方案可以实现: ✅ 实时聊天应用
✅ 金融行情看板
✅ 大文件逐块处理
✅ AI生成内容流式展示