做 AI 对话前端,流式 + Markdown 这对组合是体验担当,也是 bug 重灾区。最常见的就是——回答一边流出来一边渲染,代码块、列表写到一半时结构不完整,整个内容疯狂跳闪,看得人眼晕。
聊下我踩平这个坑的过程。
为啥会闪
Markdown 是有结构的。一个代码块 ``` 还没收尾、一个列表只写了半行时,你拿去 render,渲染器按"残缺的结构"解析,下一个 chunk 来了结构变了,又重排——于是闪。
我的解法
核心:流式期间先当纯文本追加显示,流结束后再整体按 Markdown 渲染一次。 用户看到的是流畅的打字机效果,结束瞬间"咔"地变成漂亮排版,不闪了。
let buf = '';
for await (const chunk of stream) {
buf += chunk;
renderPlainText(buf); // 流式中:纯文本,打字机感
}
renderMarkdown(buf); // 结束后:整体渲染 Markdown
我的智能体是用讯飞星辰搭、发布成 API 的,接口支持流式返回,前端这套处理就是配它的流。
还能再优化
- 想流式期间也有 Markdown 效果?可以做"安全渲染"——只渲染已闭合的结构,没收尾的先留着。但复杂,收益看场景。
- 节流:chunk 太碎,攒几个字或按帧刷一次,别每个字都 setState。
- 代码块加个复制按钮,AI 回答代码必备。
就这么个"先纯文本后 Markdown"的小处理,闪屏没了,体验顺滑。完整读流代码我放评论区了。你们流式渲染都怎么防闪的?✨