1. SSE 适用场景(单向、仅后端推文本)
核心特点:基于 HTTP、只能后端发给前端、只适合文本流式输出
- AI 问答、文案生成、代码流式返回、实时日志、消息通知
- 需求:只需要源源不断接收后端增量文字,不需要前端频繁实时上传数据
SSE 精简封装(AI 逐字流式,单向推送,代码最少)
适用:纯服务端下发、逐字打字、大模型流式输出
// sseStream.js 极简封装
export function createSSEStream(url, handlers) {
const source = new EventSource(url, { withCredentials: true });
let timer = null;
// 正常分片消息
source.onmessage = (e) => {
const res = JSON.parse(e.data);
// 逐字片段追加
if (res.data) handlers.onChunk?.(res.data);
// 流式结束
if (res.isEnd) {
handlers.onEnd?.();
source.close();
}
};
// 错误重连控制
source.onerror = () => {
handlers.onError?.();
// 连续失败关闭,避免无限重连
timer = setTimeout(() => source.close(), 8000);
};
// 主动停止流式输出
const stop = () => {
clearTimeout(timer);
source.close();
};
return { stop };
}
使用示例
// 发起对话流式输出
const stream = createSSEStream('/api/sse/stream?sessionId=xxx&token=xxx', {
// 逐字追加渲染
onChunk: (text) => {
const dom = document.getElementById('answer');
dom.innerText += text;
},
onEnd: () => console.log('回答生成完毕'),
onError: () => console.log('连接异常')
});
// 用户中断输出
// stream.stop()
2. WebSocket 适用场景(双向实时互通)
核心特点:独立 ws 协议,前后端随时互相发消息,支持二进制 / 文本
- 视频通话、实时聊天室、多人在线游戏、协同文档、直播间互动、实时监控面板
- 需求:两边要持续双向交互:你发一句、对方立刻回,还要传音频 / 视频二进制流、高频实时指令
WebSocket 极简封装(双向通信,支持心跳、自动重连、分片)
// wsStream.js 精简版,去掉冗余逻辑
export function createWSStream(url, handlers) {
let ws = null;
let reconnectTimer = null;
const heartbeatInterval = 30000;
let heartTimer = null;
// 发送心跳
const sendHeartbeat = () => ws?.readyState === 1 && ws.send(JSON.stringify({ type: 'ping' }));
// 销毁连接
const destroy = () => {
clearTimeout(reconnectTimer);
clearInterval(heartTimer);
ws?.close();
};
// 初始化连接
function connect() {
destroy();
ws = new WebSocket(url);
ws.onopen = () => {
heartTimer = setInterval(sendHeartbeat, heartbeatInterval);
handlers.onOpen?.();
};
ws.onmessage = (e) => {
const msg = JSON.parse(e.data);
// 心跳响应忽略
if (msg.type === 'pong') return;
// 流式分片
if (msg.type === 'stream/text') {
handlers.onChunk?.(msg.data);
msg.isEnd && handlers.onEnd?.();
}
};
ws.onclose = () => {
handlers.onClose?.();
// 指数退避重连
reconnectTimer = setTimeout(connect, 2000);
};
ws.onerror = () => handlers.onError?.();
}
// 主动发送消息
const send = (data) => {
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(data));
};
connect();
return { send, destroy };
}
WS 使用示例(逐字渲染对话)
const ws = createWSStream(`wss://xxx/ws/stream?token=xxx&sessionId=xxx`, {
onChunk: (char) => {
// 增量追加,逐字渲染
const box = document.querySelector('.ai-text');
box.textContent += char;
},
onEnd: () => console.log('流式完成'),
onError: () => alert('连接断开,正在重试')
});
// 主动停止生成
ws.send({ type: 'stop_stream' });
// 页面卸载销毁
window.onbeforeunload = () => ws.destroy();
选型说明
- 仅 AI 流式输出、单向推送 → 用 SSE,代码更少、无需手动心跳、浏览器自带重连
- 需要双向交互(聊天、随时发指令停止、实时操作) → WebSocket
补充两个容易踩的小细节
- 为什么视频聊天不用 SSE? 视频音频是二进制数据流,而且需要双向传输(你传画面给对方,对方也传给你),SSE 只能后端单向下发,完全做不到上传本地音视频流。
- 特殊情况:有些 AI 客户端用 WebSocket 做对话 网页端大多 SSE,手机 App / 客户端很多用 WS。因为 App 需要长期保活、多轮连续对话双向收发,WS 双向通信更方便;网页只是单次提问流式回复,SSE 更轻量化、部署简单。
一句话记: 只需要后端源源不断吐文字 → SSE; 前后两边要频繁互发消息 / 传音视频二进制 → WebSocket。