摘要:你还记得在使用某些智能应用,如 DeepSeek 时,输入问题后,答案仿佛具有魔法,能一点点地呈现在页面上吗?起初,我猜测这可能是 WebSocket 的神奇推送,但经过仔细检查网络请求,我发现并非如此,而是一种基于 HTTP 的特殊技术 —— SSE(Ser
在前端开发的浩瀚宇宙中,总有一些技术如璀璨星辰,吸引着我们不断探索。今天,就让我们一同走进 sse 流式传输的世界,感受它的独特魅力。
你还记得在使用某些智能应用,如 DeepSeek 时,输入问题后,答案仿佛具有魔法,能一点点地呈现在页面上吗?起初,我猜测这可能是 WebSocket 的神奇推送,但经过仔细检查网络请求,我发现并非如此,而是一种基于 HTTP 的特殊技术 —— SSE(Server-Sent Events)。
与 WebSocket 不同,SSE 并非基于 TCP 协议,而是依附于 HTTP 协议。它是一种单工通信模式,专为服务端向浏览器端实时推送消息而生。虽然功能相对有限,但却以其简洁轻便、易于实现而备受青睐。
为了更清晰地理解 SSE 的特点,让我们把它和 WebSocket 放在一起比较一番:
| 特性 | SSE | WebSocket | | ---
| 基础协议 | HTTP 协议 | TCP 协议 | | 通信模式 | 单工(服务端到浏览器) | 全双工(可双向通信) | | 复杂程度 | 轻量级,简单易用 | 相对复杂 | | 断线重连 | 内置断线重连功能 | 需手动实现 | | 消息类型 | 文本或经 Base64、gzip 处理的二进制消息 | 支持多种类型消息 | | 自定义事件 | 支持自定义事件类型 | 不支持自定义事件类型 | | 连接数量 | HTTP/1.1 最多 6 个,HTTP/2 默认 100 个 | 无限制 |
从表中可见,若项目需求仅为服务端向浏览器端推送消息,且希望快速实现,SSE 当然是更优之选。
在浏览器端,我们主要借助 EventSource API 来与 SSE 服务器进行交互。
建立连接 :通过 new EventSource(url) 创建实例,其中 url 为服务器端提供的接口地址。还可以传入可选的 options 参数,如 {withCredentials: true} ,用于处理跨域凭据问题。 监听事件 : EventSource 实例提供了多种事件供我们监听,包括 onopen (连接建立)、 onmessage (接收到消息)、 onerror (出现错误)。除了系统预设事件,还能自定义事件类型,只需在服务器端指定事件名称即可。为了方便在项目中使用 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); } 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 的精彩之旅,让前端应用更具活力。
来源:墨码行者