流式输出

1.发起流式请求 (ChatInput.vue - fetchMessage 函数)

typescript
const response = await fetch("/api/chat/stream", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${token}`,
  },
  body: JSON.stringify({
    message,
    session_id: sessionId,
  }),
});
  • 使用原生 fetch API 而不是 Axios(因为需要读取流)

  • 向后端 /api/chat/stream 接口发送 POST 请求

  • 携带用户消息和会话 ID

2.获取可读流

typescript
const reader = response.body?.getReader();
const decoder = new TextDecoder();
  • 通过 response.body.getReader() 获取一个可读流阅读器

  • 创建 TextDecoder 用于将二进制数据解码为文本

3.初始化 AI 消息占位符

typescript
messageStore.addAIMessage("");  // 添加一个空的 AI 消息
aiMessageIndex = messageStore.message.length - 1;  // 记录该消息的索引

4.循环读取流数据

typescript
while (true) {
  const { done, value } = await reader.read();
  if (done) break;  // 流结束时退出循环
  
  const text = decoder.decode(value, { stream: true });
  buffer += text;
  
  // 按换行符分割处理
  const lines = buffer.split("\n"); //分割成数组
  buffer = lines.pop() || "";  // 保留不完整的最后一行,pop()删除数组最后一个元素,并且返回他
  
  for (let line of lines) {
    if (line.startsWith("data: ")) {
      const jsonStr = line.slice(6); //字符串方法,从字符串索引6开始切割到末尾
      const data = JSON.parse(jsonStr); //jsonStr是{"content": "..."}这样的结构
      if (data.content) {
        fullContent += data.content;
        messageStore.updateAIMessageContent(aiMessageIndex, fullContent);// 更新状态仓库数组
      }
    }
  }
}

5.解析 SSE 格式数据

前端解析步骤:

  1. 检测行是否以 data: 开头

  2. 提取 data: 后面的 JSON 字符串

  3. 解析 JSON 获取 content 字段

  4. 累加到 fullContent 变量中

6.视图渲染

vue
<div v-else class="m-6 px-4 py-6">
  <div class="max-w-4xl mx-auto">
    <AIMarkdown :content="content" />
  </div>
</div>

7.释放资源

typescript
finally {
  reader.releaseLock();  // 释放阅读器锁
}


流式输出
http://localhost:8090/archives/liu-shi-shu-chu
作者
Administrator
发布于
2026年04月08日
许可协议