AI聊天场景,前端如何实现“打字机”效果
功能剖析ai
STAR
- 场景:用户需要AI对话实时反馈
- 任务:前端实现流式消息显示
- 行动:每条消息分多次接收,逐步拼接显示,实现“打字机”效果
- 结果:逐字显示减少焦虑,技术简单效果惊艳
技术实现:
- 后端:通过SSE流式接口,把AI回复切成多个chunk发送
- 前端:监听接口,收到的chunk拼接到现有消息字符串上
技术拓展
SSE
SSE是一种基于HTTP的服务器到客户端的单向通信技术方案,和HTTP的区别在于实现了长连接。长连接就是有别于普通 HTTP 请求的 “一次性”,对 TCP 连接进行复用。
从实现效果的角度来说,SSE 可以做到服务器持续向客户端发送数据,无需客户端重复发起请求,客户端也不会关闭连接,会一直等着服务器发过来的新的事件流。
如何实现 SSE ?和传统 HTTP 请求类似,客户端先发起请求,不过,此时客户端需要告知服务器:客户端希望接收一种特殊的、持续的事件流(event stream),方法很简单,发送请求的时候,请求头里写 Accept: text/event-stream
即可(W3C规范规定)。
此时,服务器收到请求后,不会像普通 HTTP 那样返回响应后立即关闭连接,而是保持连接打开,并通过这个长连接持续推送数据。推送的数据(也就是响应报文)也需要遵循规范:
响应行:
Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive
text/event-stream
:指定 MIME 类型,表明这是 SSE 事件流。no-cache
:禁止缓存,确保客户端接收实时数据。keep-alive
:维持长连接,避免频繁断开重连。
响应体由一系列 事件(event) 组成,每个事件由一个或多个 字段(field) 构成,字段格式为 字段名: 值
,以换行符(\n
)分隔。
// 事件1:默认类型(message),单行数据 data: 这是一条简单消息 // 事件2:指定类型(notice),多行数据 event: notice data: 这是第一行 data: 这是第二行 id: 123 retry: 5000 // 事件3:无类型,无id,仅数据 data: 另一条消息 // 两个\n表示事件结束
- data:(必选)事件的数据内容,可多行(每行以 data: 开头),最终会被拼接为一个字符串(换行符保留)。
- event:(可选)事件类型,默认值为 message。客户端可通过 addEventListener(type, ...) 监听特定类型的事件。
- id:(可选)事件的唯一标识,客户端会记录最后接收的 id,若连接断开,重连时会通过 Last-Event-ID 请求头告知服务端,用于恢复数据。
- retry:(可选)指定客户端重连的间隔时间(毫秒),默认由客户端决定(通常几秒)。
除了实现流式响应,SSE还用于实现数据监控(如股票行情、系统性能指标),日志流展示(如实时打印后端日志)。
长连接
在 HTTP/1.0 中,HTTP 请求默认是 “短连接”(一次请求后关闭连接),必须显式添加 Connection: keep-alive
才能启用长连接。
到了 HTTP/1.1 中,长连接是默认行为(即使不写 Connection: keep-alive
,连接也会保持),keep-alive
字段更多是为了兼容旧版本。
HTTP/2 和 HTTP/3 采用了更高效的[[多路复用机制]],不再依赖 keep-alive
,但仍兼容该字段(协议会直接忽略请求头中的 keep-alive
字段)。
过长的连接保持时间可能会占用服务器资源,因此服务器通常会在响应头设置合理的超时时间和最大请求数。(如 Keep-Alive: timeout=10, max=100
表示连接保持 10 秒,最多处理 100 次请求)。