前端技术大放送,SSE 流式传输全攻略
探索前端新境界:SSE 流式传输的魅力
在前端开发的浩瀚宇宙中,总有一些技术如璀璨星辰,吸引着我们不断探索。今天,就让我们一同走进 SSE 流式传输的世界,感受它的独特魅力。
一、初遇 SSE
你还记得在使用某些智能应用,如 DeepSeek 时,输入问题后,答案仿佛具有魔法,能一点点地呈现在页面上吗?起初,我猜测这可能是 WebSocket 的神奇推送,但经过仔细检查网络请求,我发现并非如此,而是一种基于 HTTP 的特殊技术 —— SSE(Server-Sent Events)。
与 WebSocket 不同,SSE 并非基于 TCP 协议,而是依附于 HTTP 协议。它是一种单工通信模式,专为服务端向浏览器端实时推送消息而生。虽然功能相对有限,但却以其简洁轻便、易于实现而备受青睐。
二、SSE 与 WebSocket 的对比
为了更清晰地理解 SSE 的特点,让我们把它和 WebSocket 放在一起比较一番:
特性 | SSE | WebSocket |
---|---|---|
基础协议 | HTTP 协议 | TCP 协议 |
通信模式 | 单工(服务端到浏览器) | 全双工(可双向通信) |
复杂程度 | 轻量级,简单易用 | 相对复杂 |
断线重连 | 内置断线重连功能 | 需手动实现 |
消息类型 | 文本或经 Base64、gzip 处理的二进制消息 | 支持多种类型消息 |
自定义事件 | 支持自定义事件类型 | 不支持自定义事件类型 |
连接数量 | HTTP/1.1 最多 6 个,HTTP/2 默认 100 个 | 无限制 |
从表中可见,若项目需求仅为服务端向浏览器端推送消息,且希望快速实现,SSE 当然是更优之选。
三、浏览器中的 SSE API
在浏览器端,我们主要借助 EventSource
API 来与 SSE 服务器进行交互。
- 1. 建立连接 :通过
new EventSource(url)
创建实例,其中 url 为服务器端提供的接口地址。还可以传入可选的 options 参数,如{withCredentials: true}
,用于处理跨域凭据问题。 - 2. 监听事件 :
EventSource
实例提供了多种事件供我们监听,包括onopen
(连接建立)、onmessage
(接收到消息)、onerror
(出现错误)。除了系统预设事件,还能自定义事件类型,只需在服务器端指定事件名称即可。
四、实战封装 SSEService 类
为了方便在项目中使用 SSE,我们可以对其进行封装,创建一个 SSEService 类。
class SSEService {
constructor() {
this.eventSource = null;
this.isClosing = false;
}
connect(url, options = {}) {
if (this.eventSource) {
this.disconnect();
}
this.eventSource = new EventSource(url);
// 连接打开时的处理
this.eventSource.onopen = () => {
console.log('SSE 连接已建立');
this.isClosing = false;
if (options.onOpen) {
options.onOpen();
}
};
// 接收到消息时的处理
this.eventSource.onmessage = event => {
try {
const data = JSON.parse(event.data);
if (options.onMessage) {
options.onMessage(data);
}
// 假设 status 为 1 表示最后一条消息
if (data.status === 1) {
this.isClosing = true;
this.disconnect();
}
} catch (error) {
console.error('解析 SSE 消息失败:', error);
}
};
// 出现错误时的处理
this.eventSource.onerror = error => {
if (this.isClosing) {
return;
}
console.error('SSE 连接错误:', error, new Date().toLocaleString());
if (options.onError) {
options.onError(error);
}
this.disconnect();
};
}
// 断开连接
disconnect() {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = null;
console.log('SSE 连接已关闭', new Date().toLocaleString());
}
}
}
export default SSEService;
在实际使用时,只需创建该类的实例,调用 connect
方法传入相应的 url 和回调函数即可。
const sseService = new SSEService();
const url = `/api/stream?query=${encodeURIComponent(query)}`;
sseService.connect(url, {
onMessage: data => {
// 在此处处理接收到的数据,如更新页面显示
console.log('收到数据:', data);
},
onError: () => {
// 处理连接错误情况
console.error('连接出错');
}
});
五、应对流式传输的“小插曲”
在开发过程中,有时会遇到使用 webpack 打包后,流式传输效果不理想的情况 —— 本应逐步显示的数据却等到全部接收完后才一次性呈现。不用担心,这通常是因为 webpack 的代理服务器配置中 compress 设置为 true 导致的。只需将其改为 false,即可恢复正常的流式传输效果。
总之,SSE 流式传输技术在特定场景下能为我们带来流畅、实时的用户体验,其简洁的实现方式也为前端开发增添了一份便利。希望本文能帮助你开启 SSE 的精彩之旅,让前端应用更具活力。