前端 AI 对话的流式魔法:逐字显示是怎么做到的

前端 AI 对话的流式魔法:逐字显示是怎么做到的 我做了什么我们团队给一个 SaaS 运营平台做了一个 AI 助手面板——客服输入客户问题,AI 在面板里逐字输出回答,用户能看到每一个字被"打出来"的过程。整个过程不涉及页面刷新,不涉及轮询,用户输入问题后立刻开始显示文字。这件事看起来简单——“不就是调个 API 然后显示吗”——但实际上,大多数 HTTP 请求是"一次性拿到全部数据再渲染",而 AI 的回复动辄几百上千字,等全部生成完才显示的话,用户会盯着白屏8-15 秒,体验极差。关键问题是:怎么让前端的文字"一边生成一边显示"?起因:传统轮询和一次性请求的困境团队一开始的方案是"前端调后端 API,后端调 AI API,后端等 AI 全部生成完再一次性返回给前端"。代码大概长这样:// 后端constaiResult=awaitaiService.generate(messages);// 等待 8-15 秒return{data:aiResult.text};用户体验是:点发送 → 转圈 8-15 秒 → 文字一次性蹦出来。我们内部测试时,有同事以为页面卡住了点刷新——因为太安静了,没有任何中间反馈。换成轮询模式也好不到哪去:// 前端轮询consttimer=setInterval(async()={constres=awaitfetch('/api/status');const{text,done}=awaitres.json();setDisplayText(text);if(done)clearInterval(timer);},500);每 500ms 拉一次,文字是一块一块蹦出来的——“你好”“,我是”“AI助手”,像在玩贪吃蛇。用户问"对比一下 A/B 方案的优劣",等了 12 秒才出完答案,中间每 500ms 抽搐一次。工具接入:SSE 流式传输问题的根源是:后端和前端之间的传输通道不支持"边生成边传输"。解决方案是让 HTTP 响应变成一条流(Stream)——后端把 AI 生成的每一个 token 实时推送给前端,前端逐字渲染。我搭建了一个基于 Astro + Solid.js 的 demo 项目,完整实现了这个流式链路。前端发送请求的核心代码:constresponse=awaitfetch('/api/generate',{method:'POST',body:JSON.stringify({messages,temperature:0.6}),signal:controller.signal,});constreader=response.body.getReader()