前端实现大模型流式输出的方法

使用 Fetch API 处理流式响应

通过 Fetch API 的 response.body 属性可以获取可读流(ReadableStream),利用 TextDecoder 逐块解析数据流。以下是一个示例代码:

async function fetchStreamingResponse(url, inputData) {
  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(inputData)
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    const chunk = decoder.decode(value, { stream: true });
    console.log(chunk); // 处理每个数据块
  }
}

使用 EventSource 接收服务器推送

对于服务器支持 Server-Sent Events (SSE) 的场景,可以通过 EventSource 监听流式数据:

const eventSource = new EventSource('/stream-endpoint');
eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // 更新UI显示流式数据
};

WebSocket 实时双向通信

建立 WebSocket 连接实现低延迟的流式传输:

const socket = new WebSocket('wss://your-backend-endpoint');
socket.onmessage = (event) => {
  const chunk = event.data;
  // 动态渲染到页面
};

优化渲染性能

对于长文本流式输出,建议使用文档片段(DocumentFragment)减少重绘次数:

const fragment = document.createDocumentFragment();
const chunkElement = document.createElement('span');
chunkElement.textContent = chunk;
fragment.appendChild(chunkElement);
document.getElementById('output').appendChild(fragment);

错误处理与中断控制

添加异常处理和手动中断逻辑:

const controller = new AbortController();
fetch(url, { signal: controller.signal })
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('请求已中止');
    }
  });

// 需要中断时调用
controller.abort();

注意事项

  • 确保后端接口支持分块传输(chunked transfer encoding)
  • 对于大模型输出,建议设置速率限制避免前端渲染压力
  • 考虑添加加载状态指示器和错误重试机制
  • 跨域场景需配置正确的 CORS 头(如 Access-Control-Allow-Origin

性能优化技巧

  • 使用防抖(debounce)技术控制渲染频率
  • 对非关键更新使用 requestAnimationFrame
  • 考虑虚拟滚动(virtual scrolling)处理超长文本
  • 压缩传输数据(如使用 gzip 或 brotli)
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐