http流式返回

  1. HTTP流式返回(Stream)是一种服务器向客户端传输数据的方式允许数据分块发送而不是一次性发送完毕。
    这样客户端可以在接收到第一部分数据时就开始处理,而不必等待整个响应完成。

  2. 应用场景:
    2.1 业务场景:图表的监听(股票行情);体育比分;ota升级进度条;chartgpt聊天消息返回
    2.2 开发场景:视频流,文件的下载

  3. 分块传输的具体过程
    3.1 客户端请求数据:客户端向服务器发送HTTP请求。
    3.2 服务器响应头:服务器发送响应头,其中包含Transfer-Encoding: chunked,表明将使用分块传输编码。
    3.3 发送数据块:数据分块并依次发送每个块
    3.4 结束块:所有数据块发送完后,服务器发送一个大小为0的结束块,表示数据传输完成。

  4. 客户端处理步骤
    4.1 读取响应头:客户端首先读取响应头(Transfer-Encoding: chunked),了解使用了分块传输编码。
    4.2 逐块处理数据:客户端依次读取每个块的大小和数据内容,并进行处理。处理完一个块后,继续读取下一个块,直到读取到大小为0的结束块。

  5. 流式返回工作原理:
    5.1 块大小:每个数据块的大小以十六进制数表示,后跟一个回车换行(CRLF,·\r\n’)。
    5.2 数据块:实际的数据块(以二进制形式传输)。
    5.3 终止块:最后一个数据块大小为0(‘01r\n\z\n’),表示数据传输结束。

ps:HTTP流式返回(也称为分块传输编码,chunked transfer encoding)实际上是通过十六进制表示块的大小,然后传输实际数据块的二进制内容。因此,流式返回的数据块以二进制形式传输,但每个数据块的大小通过十六进制来表示。

  1. 优点:
    6.1 实时性:流式返回允许客户端在接收到部分数据时就开始处理,减少了等待时间。
    6.2 减少内存消耗:服务器不需要一次性准备所有数据,适用于大数据量的传输。
    6.3 节省带宽:仅在有数据更新时传输,避免不必要的开销。

  2. 缺点:
    7.1 丢包和重传:在网络不稳定的情况下,数据块可能会丢失或损坏,导致数据不完整。虽然可以通过重传机制解决,但这增加了实现的复杂度和系统的负担。
    7.2 浏览器兼容性:并非所有浏览器都完美支持流式返回,尤其是一些老旧的浏览器,可能无法正确处理分块传输编码(Chunked Transfer Encoding)或Fetch API中的流处理。

  3. 常见问题:
    8.1 实时聊天应用:如果网络不稳定,可能导致消息丢常见问题,需要复杂的错误处理和重传机制
    8.2大文件下载:如果网络中断,文件下载可能不完整,需要支持断点续传功能。

  4. 常见优化方案:
    9.1 错误处理和重传:实现可靠的错误检测和重传机制,确保数据的完整性和正确性。
    9.2 优化连接管理:使用高效的连接管理和负载均衡技术,减少长时间连接对服务器资源的占用。
    9.3 客户端处理优化:在客户端实现高效的数据块拼接和解析逻辑,确保数据处理的顺序和正确性。

  5. 前端代码示例:

// app/api/streaming/route.js
const story = ["李焊玲是一个女汉子。","她力大无穷,","喜欢挑战各种极限运动。","有一天,","她决定去攀登一座险峻的高山。","在山脚下,","她遇到了一群正准备放弃的登山者。","李焊玲鼓励他们,","说,","只要坚持,","没有什么是不可能的。","于是,","她带领这群登山者一起向山顶进发。","一路上,","她用自己的力量帮助大家克服各种困难,","大家都被她的勇气和毅力所感染。","最终,","在李焊玲的带领下,","他们成功登上了山顶。","大家欢呼雀跃,","李焊玲却笑着说,","这只是人生中的一个小挑战,","未来还有更多的冒险等着我们。","从那以后,","李焊玲的故事在登山者中广为流传,","她成为了大家心目中的英雄。"
];export async function GET(request) {const readable = new ReadableStream({async start(controller) {// 第一块数据// controller.enqueue("\n");// 模拟延迟并逐步发送数据块const encoder = new TextEncoder();for (let i = 0; i < story.length; i++) {await new Promise((resolve) => setTimeout(resolve, story[i].length*50));controller.enqueue(encoder.encode(`${story[i]} \n`));}// 关闭流controller.close();},});return new Response(readable, {headers: {"Content-Type": "text/plain","Transfer-Encoding": "chunked",},});
}

PS:

ReadableStreamTransformStream 是 JavaScript 中用于处理流数据的接口。

ReadableStream

ReadableStream 用于从源读取数据,可以异步地获取数据。例如,可以用来读取文件、网络请求等。以下是一个基本的示例:

const readableStream = new ReadableStream({start(controller) {// 初始化数据controller.enqueue('Hello, ');controller.enqueue('World!');controller.close();},pull(controller) {// 当 consumer 请求更多数据时调用},cancel(reason) {// 当 consumer 取消读取时调用console.log('Stream cancelled, reason:', reason);}
});const reader = readableStream.getReader();reader.read().then(function processText({ done, value }) {if (done) {console.log('Stream complete');return;}console.log(value);return reader.read().then(processText);
});

TransformStream

TransformStream 用于对流数据进行转换。它接受一个输入流,并产生一个输出流。以下是一个简单的示例:

const transformStream = new TransformStream({start(controller) {// 初始化},transform(chunk, controller) {// 对每个数据块进行处理controller.enqueue(chunk.toUpperCase());},flush(controller) {// 在流结束时处理剩余的数据console.log('All chunks transformed.');}
});const readable = new ReadableStream({start(controller) {controller.enqueue('Hello, ');controller.enqueue('world!');controller.close();}
});const writable = new WritableStream({write(chunk) {console.log(chunk);},close() {console.log('All data written.');}
});readable.pipeThrough(transformStream).pipeTo(writable);

以上示例展示了如何创建一个 ReadableStream 以及如何使用 TransformStream 对数据进行转换,然后通过 pipeThrough 将转换后的数据传输到一个 WritableStream

这两个接口可以非常灵活地处理流数据,适用于许多异步数据处理场景。

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

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

相关文章

手动安装maven依赖到本地仓库

使用mvn install命令安装jar包到指定的仓库。 命令如下&#xff1a; mvn install:install-file -Dmaven.repo.localC:\Users\liyong.m2\repository -DgroupIdcom.aspose -DartifactIdwords -Dversion18.4 -Dpackagingjar -DfileC:\Users\liyong\Desktop\jar\words-18.4.jar 解释…

grafana + Prometheus + node-exporter + pushgateway + alertmanager的监控解决方案

业内比较著名的监控解决方案&#xff0c;据笔者所知&#xff0c;大概是三套&#xff1a; 一个是zabbix的解决方案&#xff0c;一个是prometheusgrafana&#xff0c;一个是ELK zabbix比较重&#xff0c;而且原生支持监控SNMP&#xff0c;自带一个仪表盘&#xff0c;不需要额外…

docker redis 持久化

1、拉取redis镜像 docker pull redis:latest 2、 mkdir /data/redis 3、填充redis.conf文件及根据需求修改相应的配置 •通过官网地址找到对应版本的配置文件 •将配置信息复制到redis.conf中 •常见的修改配置 https://redis.io/docs/latest/operate/oss_and_stack/managem…

高仿果汁导航模板

参考原文&#xff1a;果汁导航风格模板_1234FCOM专注游戏工具及源码例子分享 极速云

sdut pta 链表3(优化)-----7-3 sdut-C语言实验-链表的结点插入

7-3 sdut-C语言实验-链表的结点插入 分数 20 全屏浏览 切换布局 作者 马新娟 单位 山东理工大学 给出一个只有头指针的链表和 n 次操作&#xff0c;每次操作为在链表的第 m 个元素后面插入一个新元素x。若m 大于链表的元素总数则将x放在链表的最后。 输入格式: 多组输入。…

基于springboot的毕业设计系统的开发源码

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的毕业设计系统的开发。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 毕业设计系统能够实现…

学习通高分免费刷课实操教程

文章目录 概要整体架构流程详细步骤云上全平台登录步骤小结 概要 我之前提到过一个通过浏览器的三个脚本就可以免费高分刷课的文章&#xff0c;由于不方便拍视频进行实操演示&#xff0c;然后写下了这个实操教程&#xff0c;之前的三个脚本划到文章末尾 整体架构流程 整体大…

窗口函数 | rows between …… and ……

ROWS BETWEEN ... AND ... 是 SQL 窗口函数中的一个子句&#xff0c;用于定义窗口函数操作的行范围。窗口函数允许用户对一组相关的记录执行计算&#xff0c;这些记录被称为窗口。 基本语法 <窗口函数> OVER ( [PARTITION BY <列名>] ORDER BY <列名> [AS…

前端基础入门三大核心之HTML篇 —— SVG的viewBox、width和height:绘制矢量图的魔法比例尺【含代码示例】

前端基础入门三大核心之HTML篇 —— SVG的viewBox、width和height&#xff1a;绘制矢量图的魔法比例尺【含代码示例】 基本概念与作用viewBoxwidth和height 代码示例与实践基础示例动态调整示例 不同角度的使用思路保持比例缩放自动适应容器 实际问题与解决方案结语与讨论 在前…

华为云之Zabbix监控平台部署实践

华为云之Zabbix监控平台部署实践 一、本次实践介绍1.1 实践环境简介1.3 本次实践完成目标 二、 相关服务介绍2.1 华为云ECS云服务器介绍2.2 Zabbix介绍 三、环境准备工作3.1 预置实验环境3.2 查看预置环境信息 四、登录华为云4.1 登录华为云4.2 查看ECS状态4.3 连接ECS弹性云服…

力扣HOT100 - 287. 寻找重复数

解题思路&#xff1a; 快慢指针 第一步&#xff0c;慢指针每次移动一步&#xff0c;快指针每次移动两步&#xff0c;直到它们相遇。这一步保证了它们在环中相遇。 接下来&#xff0c;将其中一个指针&#xff08;快指针或慢指针&#xff09;重置到起点&#xff08;即数组的第一…

SpringBoot实现邮箱验证码

自行创建一个SpringBoot项目 导入SpringBoot所需要的邮箱验证码的包 <!--邮件发送--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><version>2.6.1</version>…

前后端部署笔记

windows版&#xff1a; 如果傻呗公司让用win电脑部署&#xff0c;类似于我们使用笔记本做局域网服务器&#xff0c;社内使用。 1.安装win版的nginx、mysql、node、jdk等 2.nginx开机自启参考Nginx配置及开机自启动&#xff08;Windows环境&#xff09;_nginx开机自启动 wind…

UPPAAL使用方法

UPPAAL使用方法 由于刚开始学习时间自动机及其使用方法&#xff0c;对UPPAAL使用不太熟悉&#xff0c;网上能找到的教程很少&#xff0c;摸索了很久终于成功实现一个小例子&#xff0c;所以记录一下详细教程。 这里用到的例子参考【UPPAAL学习笔记】1&#xff1a;基本使用示例…

专业级润滑油,一站式批发服务

要为机械设备提供持久稳定的动力保障吗&#xff1f;选择我们的专业级润滑油&#xff0c;让您的设备运转更顺畅&#xff0c;效率更高。 我们专业从事润滑油批发多年&#xff0c;以优质的产品、合理的价格和完善的服务赢得了广大客户的信赖。无论是汽车、机械还是工业设备&#x…

【Vue3】env环境变量的配置和使用(区分cli和vite)

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、env文件二、vue3cli加载env1..env配置2..dev配置&#xff08;其他环境参考&#xff09;3.package.json文件4.使用 三、vue3vite加载e…

【html5】03-新表单元素及属性

目录 1 引言 2 智能表单控件-type 3 表单属性 form input 5 答疑--解决required自定义提示信息 1 引言 HTML5引入了一系列新的表单输入类型&#xff0c;如email、url、number、range、date、time、datetime-local、month、week、search、color和tel等。这些新类型增强了表…

FFmpeg源码:bytestream_get_byte函数解析

一、引言 FFmpeg源码中经常使用到bytestream_get_byte这个函数&#xff0c;比如使用FFmpeg对BMP图片进行解析&#xff0c;其源码会调用函数bmp_decode_frame&#xff0c;而该函数内部会通过bytestream_get_byte读取BMP 的header。本文讲解函数bytestream_get_byte的作用和内部…

Spark SQL 中DataFrame DSL的使用

在上一篇文章中已经大致说明了DataFrame APi,下面我们具体介绍DataFrame DSL的使用。DataFrame DSL是一种命令式编写Spark SQL的方式&#xff0c;使用的是一种类sql的风格语法。 文章链接&#xff1a; 一、单词统计案例引入 import org.apache.spark.sql.{DataFrame, SaveMod…

在SpringBoot中添加自定义增强SpringEvent事件组件

场景说明&#xff1a;在使用SpringBoot时&#xff0c;总是要添加一大堆自定义事件&#xff0c;实现ApplicationEvent&#xff0c;来实现事件发送。 这样写代码量非常大。为了方便和避免出错&#xff0c;封装自定义的模块&#xff0c;快速实现泛型中调用SpringEvent实现事件。省…