js fetch流式请求 AI动态生成文本,实现逐字生成渲染效果

news2025/5/13 19:20:53
  1. 开启流式请求:向后端接口发起普通的 fetch,它会返回一个包含 ReadableStream 的 Response 对象
  2. 获取流式读取器:调用 response.body.getReader() 获取一个 ReadableStreamDefaultReader 实例
  3. 循环读取数据块:在 while(true) 循环或 for await 中,通过 reader.read() 或 for await (const chunk of response.body.values()) 拿到 Uint8Array 块
  4. 解码并追加显示:使用 TextDecoder 将二进制数据解码成字符串,然后每获取一段就更新到页面上,无需等待完整返回
    MDN Web Docs

发起流式

const response = await fetch('/api/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ prompt: '你好,AI。' })
});
// response.body 即为 ReadableStream

fetch 默认支持流式响应,response.body 就是一个可读流

获取并使用 Reader

const reader = response.body.getReader();  // 锁定流,获取 reader 实例
const decoder = new TextDecoder('utf-8'); // 用于将 Uint8Array 解码为字符串
let done = false;

while (!done) {
  const { value, done: streamDone } = await reader.read();
  done = streamDone;
  if (value) {
    const chunkText = decoder.decode(value, { stream: true });
    // 这里拿到了一段字符串 chunkText
    appendToPage(chunkText);
  }
}

reader.read() 每次返回一个包含 { value: Uint8Array, done: boolean } 的 Promise
传入 { stream: true } 可以确保多次调用 decode 时不会丢失跨块字符

将数据边读边显示

<div id="chat"></div>
<script>
  function appendToPage(text) {
    const chat = document.getElementById('chat');
    chat.textContent += text;  // 或者用 chat.innerHTML += 转义/格式化后追加
  }
</script>

每次读取到 chunkText,就调用一次 appendToPage,实时更新 DOM,无需等到 done === true

React 示例

import React, { useState, useEffect } from 'react';

function StreamingChat({ prompt }) {
  const [text, setText] = useState('');

  useEffect(() => {
    let cancelled = false;

    async function fetchStream() {
      setText('');
      const res = await fetch('/api/chat', { method: 'POST', body: JSON.stringify({ prompt }) });
      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let done = false;

      while (!done && !cancelled) {
        const { value, done: streamDone } = await reader.read();
        done = streamDone;
        if (value) {
          const chunk = decoder.decode(value, { stream: true });
          // 追加新内容
          setText(prev => prev + chunk);
        }
      }
    }

    fetchStream();
    return () => { cancelled = true; };
  }, [prompt]);

  return <pre style={{ whiteSpace: 'pre-wrap' }}>{text}</pre>;
}

export default StreamingChat;

拓展与注意事项

  • 错误处理:在 reader.read() 或 fetch 抛错时,捕获后展示重试选项
  • 性能优化:若数据量巨大,可考虑每累积一定长度再更新一次状态,避免过多重渲染
  • 兼容性:Safari 对流式 API 支持不完全,若需兼容可使用 polyfill 或退回到普通 fetch().then(res => res.text())
  • 流式 JSON:若后端返回的是以换行分隔的 JSON 对象流,可在 decoder.decode 后按 \n 切分并 JSON.parse 逐条处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第8章-2 查询执行的基础

上一篇&#xff1a;《第8章-1 查询性能优化-优化数据访问》&#xff0c;接着来了解查询执行的过程&#xff0c;这个对sql执行有个更直观的了解。 查询执行的基础 当希望MySQL能够以更高的性能运行查询时&#xff0c;最好的办法就是弄清楚MySQL是如何优化和执行查询的。一旦理解…

java面试OOM汇总

在正式 Minor GC 前&#xff0c;JVM 会先检查新生代中对象&#xff0c;是比老年代中剩余空间大还是小。假如 Minor GC之后 Survivor 区放不下剩余对象&#xff0c;这些对象就要进入老年代 老年代剩余空间大于新生代中的对象大小&#xff0c;那就直接 Minor GC&#xff0c; GC 完…

react-diff-viewer 如何实现语法高亮

前言 react-diff-viewer 是一个很好的 diff 展示库&#xff0c;但是也有一些坑点和不完善的地方&#xff0c;本文旨在描述如何在这个库中实现自定义语法高亮。 Syntax highlighting is a bit tricky when combined with diff. Here, React Diff Viewer provides a simple rend…

自定义prometheus exporter实现监控阿里云RDS

# 自定义 Prometheus Exporter 实现多 RDS 数据采集## 背景1. Prometheus 官网提供的 MySQL Exporter 对于 MySQL 实例只能一个进程监控一个实例&#xff0c;数据库实例很多的情况下&#xff0c;不方便管理。 2. 内部有定制化监控需求&#xff0c;RDS 默认无法实现&#xff0c;…

【计算机网络】--tcp三次握手

文章目录 示意图&#xff1a;抓包结果&#xff1a;第一次握手&#xff08;Client → Server&#xff09;第二次握手&#xff08;Server → Client&#xff09;第三次握手&#xff08;Client → Server&#xff09;为什么是三次握手 不是两次或者四次 示意图&#xff1a; 抓包结…

UI-TARS: 基于视觉语言模型的多模式代理

GitHub&#xff1a;https://github.com/bytedance/UI-TARS 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI 基于视觉语言模型&#xff08;Vision-Language Model&#xff09;的 GUI 代理应用&#xff0c;允许用户通过自然语言控制电脑操…

Spark SQL 运行架构详解(专业解释+番茄炒蛋例子解读)

1. 整体架构概览 Spark SQL的运行过程可以想象成一个"SQL查询的加工流水线"&#xff0c;从原始SQL语句开始&#xff0c;经过多个阶段的处理和优化&#xff0c;最终变成分布式计算任务执行。主要流程如下&#xff1a; SQL Query → 解析 → 逻辑计划 → 优化 → 物理…

【计算机网络】网络IP层

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 上篇文章&#xff1a;传输层协议TCP 下篇文章&#xff1a;数据链路层 文章摘要&#xff1…

一天学会Maven

一、Maven简介和快速入门 1.1 Maven介绍 Maven 是一款为 Java 项目构建管理、依赖管理的工具&#xff08;软件&#xff09;&#xff0c;使用 Maven 可以自动化构建、测试、打包和发布项目&#xff0c;大大提高了开发效率和质量。 总结&#xff1a;Maven就是一个软件&#xf…

变量函数实战:高保真APP原型“发票页面”动态交互教程

变量函数是高保真交互原型设计中常见的高级交互功能&#xff0c;能够避免重复复制与手动修改页面元素和逻辑标注&#xff0c;让演示更有真实体验感。本文分享一个高保真APP交互原型页面的实操案例&#xff0c;结合原型设计工具中的变量函数与逻辑判断功能&#xff0c;手把手教你…

Spring Boot 3 + Undertow 服务器优化配置

优化背景 当你的application需要支持瞬时高并发的时候&#xff0c;tomcat已经不在是最优的选择&#xff0c;我们可以改为Undertow&#xff0c;并对其进行优化。 Undertow 是一个轻量级的、高性能的Java Web 服务器&#xff0c;由JBoss 开发并开源。它是基于非阻塞&#xff08;…

7系列 之 OSERDESE2

背景 《ug471_7Series_SelectIO.pdf》介绍了Xilinx 7 系列 SelectIO 的输入/输出特性及逻辑资源的相关内容。 第 1 章《SelectIO Resources》介绍了输出驱动器和输入接收器的电气特性&#xff0c;并通过大量实例解析了各类标准接口的实现。 第 2 章《SelectIO Logic Resource…

vue3+flask+sqlite前后端项目实战

基础环境安装 pycharm 下载地址&#xff1a; https://www.jetbrains.com/zh-cn/pycharm/download/?sectionwindows vscode 下载地址 https://code.visualstudio.com/docs/?dvwin64user python 下载地址 https://www.python.org/downloads/windows/ Node.js&#xff08;含npm…

Java 线程的堆栈跟踪信息

Java 线程的堆栈跟踪信息&#xff0c;展示了线程的当前状态和执行位置。以下是详细解释&#xff1a; 线程基本信息 "Thread-0" #16 prio5 os_prio0 cpu0.00ms elapsed16.29s tid0x00000243105a4130 nid0x5384 waiting on condition [0x0000007687ffe000]线程名称…

【计算机视觉】OpenCV实战项目:Long-Exposure:基于深度学习的长时间曝光合成技术

Long-Exposure&#xff1a;基于深度学习的长时间曝光合成技术 项目概述与技术背景项目核心功能技术原理 环境配置与安装硬件要求建议详细安装步骤可选组件安装 实战应用指南1. 基础使用&#xff1a;视频转长曝光2. 高级模式&#xff1a;自定义光轨合成3. 批量处理模式 技术实现…

传输层协议UDP和TCP

传输层协议UDP和TCP 1、UDP2、TCP2.1、TCP协议段格式2.2、确认应答(ACK)机制2.3、超时重传机制2.4、连接管理机制2.5、理解CLOSE_WAIT状态2.6、理解TIME_WAIT状态2.7、流量控制2.8、滑动窗口2.9、拥塞控制2.10、延迟应答2.11、捎带应答2.12、面向字节流2.13、粘包问题2.14、TCP…

浅谈大语言模型原理

1.反向传播算法 背景 反向传播算法是当前深度学习的核心技术。 神经网络 x是输入&#xff0c;o是输出&#xff0c;w是需要训练的参数&#xff08;w有初始值&#xff09;三层全连接的神经网络&#xff1a;输入层、隐藏层、输出层 激活函数 f ( x ) 1 1 x − 1 f(x)\frac…

Clickhouse 迁移到 Doris 的最佳实践

一、引言 在将数据从 Clickhouse 迁移到 Apache Doris / SelectDB Cloud 的过程中&#xff0c;涉及表结构迁移、查询语句迁移以及数据迁移等多个关键环节。每个环节都有其复杂性和需要注意的细节&#xff0c;本文将详细介绍这些内容及对应的最佳实践方法。 二、表结构迁移 &…

WebSocket的原理及QT示例

一.WebSocket 介绍 1.概述 WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议&#xff0c;它在 2011 年被 IETF 定为标准 RFC 6455&#xff0c;并由 RFC7936 补充规范。与传统的 HTTP 协议不同&#xff0c;WebSocket 允许服务器和客户端之间进行实时、双向的数据传输&a…

vue3:十二、图形看板- echart图表-柱状图、饼图

一、效果 如图展示增加了饼图和柱状图,并且优化了浏览器窗口大小更改,图表随着改变 二、 饼图 1、新建组件文件 新增组件EchartsExaminePie.vue,用于存储审核饼图的图表 2、写入组件信息 (1)视图层 写入一个div,写入变量chart和图表宽高 <template><div ref…