解决从deepseek接口获取的流式响应输出到前端都是undefined的问题

在这里插入图片描述
你的前端 EventSource 代码遇到了 undefined 连续输出 的问题,通常是因为:

  1. AI 返回的内容被拆成了单个字符,导致前端 JSON.parse(event.data).content 获取到的是单个字符,而 undefined 可能是因为某些数据块没有 content 字段。
  2. 前端拼接字符串时,错误地处理了 undefined,导致 undefined 被拼接到页面上。

✅ 解决方案

1️⃣ 修正后端(确保 AI 输出的是 “块” 而不是单个字符)

你的 AI 可能逐字符返回内容,需要在后端 合并成合理的块,然后以 SSE 格式输出:

import json

def generate_category_description(messages, client):
    """调用 DeepSeek API 并流式返回符合 SSE 格式的 JSON"""
    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=messages,
        response_format={"type": "json_object"},
        stream=True  # 设置为 True,以便接收流式数据
    )

    buffer = ""  # 临时存储数据,防止单字符输出

    for chunk in response:
        if not chunk.choices:
            continue  # 跳过空数据

        content = chunk.choices[0].delta.content or ""  # 取 AI 返回的内容
        buffer += content  # 逐步累积内容

        if len(buffer) >= 10:  # 只有在积累到 10 个字符后才发送
            print(buffer, end='', flush=True)  # 实时流式输出到控制台
            yield f"data: {json.dumps({'content': buffer})}\n\n"
            buffer = ""  # 发送后清空 buffer

    # 发送剩余的内容(如果有的话)
    if buffer:
        yield f"data: {json.dumps({'content': buffer})}\n\n"

2️⃣ 修正前端(处理 undefined 并正确拼接流式数据)

你的 EventSource 代码没有正确处理 undefined,需要修正:

async function generateCategoryDesc() {
  const eventSource = new EventSource("/generate_category_desc_stream");
  let contentBuffer = ""; // 存储完整的内容

  eventSource.onmessage = (event) => {
    try {
      console.log("Raw event data:", event.data);
      const data = JSON.parse(event.data);

      if (data.content) {  // 确保 content 存在
        contentBuffer += data.content; // 拼接完整内容
        document.getElementById("editArea").innerHTML = contentBuffer; // 更新页面
      }
    } catch (err) {
      console.error("JSON parse error:", err, "Raw event data:", event.data);
    }
  };

  eventSource.onerror = (err) => {
    console.error("EventSource failed:", err);
    eventSource.close();
  };

  eventSource.onopen = () => {
    console.log("SSE connection opened.");
  };
}

🔥 关键修正

后端:

  • 确保 buffer 缓冲字符,防止逐字符发送
  • 积累到足够字符后才 yield,防止前端 undefined 乱拼接
  • 如果 AI 只返回一个字符,后端会等到 10 个字符后才发送

前端:

  • 检查 data.content 是否为 undefined,避免拼接 undefined
  • 修正 EventSource 解析逻辑,确保流式数据完整
  • 修正 contentBuffer 逻辑,确保拼接的数据正确

🚀 结果

  • 流式 AI 输出不会拆成单个字符
  • 前端不会出现 undefined
  • 文本会按块(10 字符)更新到 editArea
  • AI 生成的内容仍然是流式的,不影响流式体验

现在试试看,你的 editArea 应该会正常流式更新,而不会出现 undefinedundefinedundefined 的问题了!

### 前端实现 DeepSeek 流式传输 为了实现在前端通过 DeepSeek 进行流式传输,可以采用基于 WebSocket 或 EventSource 的技术来建立持久连接并接收服务器推送的数据。对于 HTTP 请求来说,也可以利用 Fetch API 结合 `ReadableStream` 来处理响应中的部分读取。 #### 使用 WebSocket 实现流式通信 WebSocket 提供了一种全双工的通信机制,在客户端和服务端之间保持长期打开的状态,非常适合用于实时应用开发。下面是一个简单的 JavaScript 例子展示如何创建一个 WebSocket 客户端: ```javascript const socket = new WebSocket('ws://localhost:8080/deepseek/chat-stream'); socket.onopen = function() { console.log('Connected to server'); }; socket.onmessage = function(event) { const message = JSON.parse(event.data); console.log(`Received from server ${message.content}`); }; ``` 此代码片段展示了怎样初始化一个到指定 URL 的 WebSocket 链接,并定义了当链接成功建立以及收到消息时的行为[^1]。 #### 利用 Fetch 和 ReadableStream 处理流式数据 如果更倾向于 RESTful 接口而非 WebSocket,则可以通过现代浏览器支持的 Fetch API 及其内置的支持来进行流式操作。这里给出一段演示如何监听来自服务端持续更新的内容并通过 DOM 更新界面的例子: ```javascript fetch('http://localhost:8080/deepseek/chat-stream', { method: 'POST' }) .then(response => response.body.pipeThrough(new TextDecoderStream()).getReader()) .then(reader => readStream(reader)); async function readStream(reader){ while(true){ let {done,value} = await reader.read(); if(done){break;} document.getElementById("output").innerHTML += value; } } ``` 上述脚本首先发起 POST 请求至目标地址获取返回体作为可读流对象 (`response.body`) ,之后将其转换成 UTF-8 编码字符串再逐字节读入页面元素中显示出来[^2]。 #### 构建环境配置 确保项目的依赖项已经正确设置好,特别是针对 Java 后端而言应当引入必要的库文件如 Spring Web 和 Lombok 等工具包以便更好地管理和简化编码工作流程[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值