news 2026/4/21 10:26:44

ai对话平台流式响应输出怎么实现?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ai对话平台流式响应输出怎么实现?

流式响应输出

用户发送问题后,AI 回答非一次性全部输出,而是生成一段输出一段;后端调用大模型时需设置stream=true,模型服务边生成边推送数据块,后端持续读取并实时转发给前端,前端实时渲染。

  1. 实现技术

主流实现流式输出有 3 种方式:HTTP 分块传输编码、SSE、WebSocket。项目选用SSE实现流式输出,SSE 提供了一种简单的、实时的服务器推送数据给客户端的方法。SSE建立在HTTP协议之上,无需复杂协议升级,无专门服务器支持,实现与维护成本低;专为服务器向客户端单向数据流设计,适配 AI 平台回答输出场景;相比 WebSocket 开销更小,无需处理双向消息逻辑;连接意外中断时,内置自动重连机制,提供更稳定的体验。

  1. 实现方案

前端主流方案:fetch + ReadableStream,优势在于:首先他是完全可控的,可精细控制 POST 请求、headers 与数据处理,灵活性很高;然后他的与各大模型官方 API 的标准完全对齐;可分块接收数据,实现打字机效果。

原生EventSource也可以实现:简单、自带重连、浏览器原生支持,但是存在局限,它仅支持 GET 方法不支持自定义 Request Headers(这是由 HTML5 规范定义的标准行为),因此无法直接携带 Token 进行鉴权,也不适合提交复杂的 POST 业务参数。并且readablestream提供了对字节级流的精细化控制,适合做文本增量解析。同时,底层网络传输和streams api返回的数据是原始的二进制(uint8array),必须解码成字符串之后才能进行后续处理,fetch readablestream 返回的是二进制块,这里就要用textdecoder将uint8array解码为js字符串,才能用jsonprase或者是data:前缀,流式输出的过程中,用textdecoder(utf-8,{stream:true})对字节流进行增量解码,保证跨chunk的字符能够被正确还原。所以项目流式输出的方案是更灵活的Fetch API + ReadableStream+textdecoder。
核心流程:用 fetch 发送 POST 请求到后端 API;ReadableStream 接收服务端返回的流式数据;分块读取和处理数据,解码拼接实现实时展示;渲染优化:使用buffer 缓冲配合 RAFrequest Animation Frame批量刷新,减少冗余 DOM 操作。这里为什么要进行一个渲染优化呢,如果每次收到数据块chunk直接操作DOM.innerHTML会引发频繁重排(reflow)和重绘(repaint),导致页面卡顿。
优化方案:我这里是设置了一个缓冲区,累积若干 chunk 或等待短时间(16ms),再更新 DOM;利用requestAnimationFrame控制渲染频率(让他和浏览器60fps屏幕刷新频率一致),与浏览器渲染周期同步,避免掉帧,无内容时自动停止渲染,页面不可见时暂停执行。

  1. 流式中断处理与异常重试机制

在流式渲染中,网络波动或者后端异常,会导致readablestream/SSE中断,不处理的话,用户会看到对话突然停止,用户体验差。

流式中断处理通常分为四步:

捕获异常和超时,判断流是不是中断了;缓存已经接收的文本,记录最后渲染的位置;根据最大重试次数尝试重连或者续流;恢复之后按照原有分批渲染逻辑输出,同时保证滚动和用户感知。

  • 中断检测

判断异常是人为还是异常中断

异常捕获,在fetch、readerread时捕获异常

超时检测,使用心跳保活机制,每 30 秒向服务器发送一次心跳请求,防止长连接超时;心跳请求设置 5 秒超时,不阻塞主流程。服务端每隔几秒向流连接发送空数据,在ReadableStream中加入心跳逻辑,每 5s 推送一个空心跳 chunk,前端过滤心跳 chunk,有数据即代表连接活跃,避免长时间静默断开。

  • 缓存已经接收的数据-断点续传

通过receiveChunks数组存储已接收消息片段;前端重试时,保证同一点的重试请求服务端只处理一次,避免重复生成内容(幂等性保证)。

  • 重连、恢复机制

实现了带重试的fetch请求,支持网络错误和特定的http状态码429、500、502、504。

429:用户发送请求太多、被限流(并发请求太多、被服务商暂时拒绝,单位时间调用次数超了);500:AI 服务器内部出错(临时服务故障、AI 服务 / 网关负载过高挂掉、后端服务重启中);502:网管坏了、代理服务器挂了(ai服务商网管或负载均衡挂了、后端服务重启中、网络链路抖动);503:服务暂不可用(ai模型正在扩容、重启、维护,服务其过载);504:网关超时(AI 服务未返回、服务负载高、处理慢、网络链路延迟大)。遇到以上几个状态码时会自动重试,重试的过程是采用指数退避策略:每次重试延迟时间指数增长,添加随机抖动因子(0.8-1.2)避免多个请求同时重试,达最大重试次数后向用户返回错误。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 10:24:51

新手避坑指南:在Vivado 2022.1上为Nexys A7-100T创建第一个流水灯项目

Vivado 2022.1与Nexys A7-100T实战:从零开始构建流水灯项目的完整避坑指南 第一次接触FPGA开发的新手们,当你拿到Nexys A7-100T这块功能强大的开发板,安装好Vivado 2022.1这个庞大的工具链时,内心可能既兴奋又忐忑。流水灯作为数字…

作者头像 李华
网站建设 2026/4/21 10:24:09

Mac新手必看:从bash切换到zsh后,Maven、Brew命令失效的保姆级修复指南

Mac开发者必备:zsh环境变量迁移全攻略与效率提升指南 刚把Mac的默认shell从bash切换到zsh时,那种"昨天还能用的命令今天全报错"的恐慌感我至今记忆犹新。Maven构建失败、brew命令失踪,连最基本的工具都集体罢工——这其实是每个Mac…

作者头像 李华
网站建设 2026/4/21 10:23:33

揭开虚幻引擎Pak文件的黑盒:UnrealPakViewer如何重塑资源管理体验

揭开虚幻引擎Pak文件的黑盒:UnrealPakViewer如何重塑资源管理体验 【免费下载链接】UnrealPakViewer 查看 UE4 Pak 文件的图形化工具,支持 UE4 pak/ucas 文件 项目地址: https://gitcode.com/gh_mirrors/un/UnrealPakViewer 在虚幻引擎开发的日常…

作者头像 李华
网站建设 2026/4/21 10:21:40

别再只会pacman了!用yay和AUR解决Manjaro软件安装的‘老大难’问题

解锁Manjaro软件生态:从pacman到AUR的进阶实战指南 当你在Manjaro上尝试安装微信或QQ时,是否经历过这样的挫败感?官方仓库的pacman命令报出一连串依赖错误,而论坛里那些"一行命令搞定"的教程对你却毫无作用。这并非你的…

作者头像 李华
网站建设 2026/4/21 10:20:36

GNSS接收机选型避坑指南:如何从多路径抗干扰能力评估设备好坏?

GNSS接收机选型实战:多路径抗干扰能力评估全攻略 站在城市峡谷的阴影中,手持GNSS接收机的工程师眉头紧锁——屏幕上跳动的坐标与预期相差了整整三米。这不是科幻场景,而是高精度定位项目中的日常困境。多路径效应如同光学中的"鬼影"…

作者头像 李华
网站建设 2026/4/21 10:19:05

2026年北京美术培训费用全解析

随着家长对美育教育的重视程度不断提升,美术培训市场也日益繁荣。在北京这样一个教育资源丰富的城市,选择合适的美术培训机构不仅关系到孩子的艺术发展,还直接涉及到家庭的经济负担。本文将从多个角度对比分析北京几家知名美术培训机构的费用…

作者头像 李华