You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TextDecoderStream读取OpenAI API流时截断,如何获取完整块?

解决OpenAI流式响应读取时最后一行截断的问题

标签:openai-api

在读取OpenAI Completions的流式响应时,直接用TextDecoderStream配合读取器循环读取,常会遇到最后一行数据被截断的情况——这是因为字节流的分片是随机的,reader.read()返回的内容不一定刚好在换行符处结束,导致最后一次读取的是不完整的JSON片段。

要确保接收完整数据块,核心思路是维护一个缓冲区缓存未完成的行,具体实现如下:

  • 初始化一个空字符串作为缓冲区,每次读取到内容后先追加到缓冲区中。
  • 按换行符\n分割缓冲区,只处理分割后的完整行,把最后一段可能不完整的内容重新放回缓冲区。
  • 当读取器标记done为true时,处理缓冲区中剩余的最后一行内容(这就是之前被截断的部分)。

示例代码:

let buffer = '';
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();

while (true) {
  const { done, value } = await reader.read();
  if (done) {
    // 处理最后剩余的未完成行
    if (buffer.trim()) {
      processIncompleteLine(buffer);
    }
    break;
  }

  buffer += value;
  const lines = buffer.split('\n');
  // 把最后一行(可能不完整)留回缓冲区
  buffer = lines.pop() || '';

  // 处理所有完整的行
  for (const line of lines) {
    const trimmedLine = line.trim();
    if (!trimmedLine) continue; // 跳过空行
    if (trimmedLine.startsWith('data:')) {
      const jsonContent = trimmedLine.slice(5).trim();
      if (jsonContent === '[DONE]') continue; // 忽略结束标记
      try {
        const chunk = JSON.parse(jsonContent);
        // 这里替换成你的chunk处理逻辑
        console.log('完整chunk:', chunk);
      } catch (err) {
        console.error('JSON解析失败:', err);
      }
    }
  }
}

function processIncompleteLine(line) {
  const trimmedLine = line.trim();
  if (trimmedLine.startsWith('data:')) {
    const jsonContent = trimmedLine.slice(5).trim();
    try {
      const chunk = JSON.parse(jsonContent);
      console.log('最后一行完整chunk:', chunk);
    } catch (err) {
      console.error('最后一行解析失败:', err);
    }
  }
}

注意事项:

  • 必须处理done状态下的缓冲区剩余内容,这是解决截断问题的关键。
  • OpenAI流式响应的每行以data:开头,最后会返回data: [DONE]作为结束信号,需要过滤该标记。
  • 分割行时要处理空行,避免无效解析。

内容的提问来源于stack exchange,提问作者Luc Gagan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 05:25:39