前端接收流式数据的完整方案(SSE/WebSocket/Fetch API)
一、流式数据
什么是流式数据?
- 数据分多次传输,无需等待完整内容即可开始处理
- 典型场景:实时日志、股票行情、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-stream
Cache-Control: no-cache
Connection: 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');
};
协议对比:
| 维度 | SSE | WebSocket |
|---|---|---|
| 协议 | HTTP | WS/WSS |
| 方向 | 单向 | 双向 |
| 二进制支持 | 仅文本 | 支持二进制 |
| 自动重连 | ✅ | ❌ |
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.js
self.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(); }; -
错误恢复
// 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
六、服务端配合要求
| 技术 | 响应头 | 数据格式 |
|---|---|---|
| SSE | text/event-stream | data: {...}\n\n |
| WebSocket | Upgrade: websocket | 二进制/文本 |
| Fetch | Transfer-Encoding: chunked | 分块编码 |
上面这些方案可以实现:
✅ 实时聊天应用
✅ 金融行情看板
✅ 大文件逐块处理
✅ AI生成内容流式展示