首页 web前端 js教程 Chunk-Busters:不要跨越溪流!

Chunk-Busters:不要跨越溪流!

Dec 02, 2024 am 05:00 AM

⚠️ 如果您有光敏性,您可能想跳过此操作。
请参阅下面的静态图片,这些灯将开始快速闪烁!

Chunk-Busters: Don’t cross the Streams!

互联网如何运作?

记住标题……我们在这里讨论的是流。

我可以谈论协议、数据包、排序、acks 和 nacks…但我们在这里谈论流,正如你可能猜对了(我相信你=D)流…它要么是二进制,要么是字符串。

是的,字符串在发送之前会被压缩……但是对于我们在前后端开发中通常关心的内容……字符串和二进制。

在下面的示例中,我将使用 JS 流。

虽然 Node 有自己的遗留实现,但我们有办法处理相同代码的流,无论是在前面还是后面。

其他语言有自己处理流的方式,但正如你所看到的......处理它的实际代码部分并不复杂(并不是说没有发生复杂的事情)。

示例问题

您的前端必须使用多个来源的数据。

虽然您可以通过其 IP/端口单独访问每个源,但您可以将它们放在 API 网关后面以便于使用和控制。

回购协议

检查链接中的存储库,了解如何自己运行它,以便您可以使用它。

https://github.com/Noriller/chunk-busters

视频

后续视频版本:

https://youtu.be/QucaOfFI0fM

v0 - 简单的实现

您拥有源,您可以获取、等待和渲染。冲洗并重复。

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
登录后复制
登录后复制

你可能会认为没有人会真正这么做......

在这个例子中,很明显出了问题,但陷入这个问题并不难。

显而易见:它很慢。你必须触发并等待每个请求,如果速度很慢……你就必须等待。

v1 - 渴望版本

您知道您不想单独等待每个请求......因此您触发所有请求,然后等待它们完成。

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
登录后复制
登录后复制

这就是你可能会做的事情,所以这很好,对吧?

我的意思是,除非您有一个请求速度很慢……这意味着即使所有其他请求都已完成……您仍然必须等待该请求完成。

v2 - 更智能、更热心的版本

你知道你可能有一些较慢的请求,所以你仍然触发所有请求并等待,但当它们到来时,你已经在可能的情况下对结果做了一些事情,所以当最后一个请求到达时,其他请求已经完成。

await fetch1();
handleResult(1);
await fetch2();
handleResult(2);
...
await fetch9();
handleResult(9);
登录后复制
登录后复制

这一定是最好的解决方案,对吧?

嗯……有什么奇怪的吗?

v3 - 我在骗你……这就是 v1 应该的样子

还记得 v1 吗?是的...它应该是这样的:

事实证明,在 http/1 中同一个端点可以拥有的连接数量是有限制的,不仅如此……它还依赖于浏览器,并且每个浏览器可能有不同的限制。

您可能会认为只使用 http/2 就到此为止了……但即使这是一个很好的解决方案,您仍然需要在前端处理多个端点。

有没有好的解决方案?

v4 - 进入流!

让我们回顾一下 v0,但使用流......

你很聪明,所以你可能已经预料到了这一点,因为警告有点破坏了它......但是,是的......你之前看到的并不是后端生成的所有数据。

无论如何……当我们获取时我们就会渲染。

await Promise.all([
  fetch1(),
  fetch2(),
  ...
  fetch9(),
]);
handleAllResults(results);
登录后复制
登录后复制

如果我们点击即将到来的流,我们就可以对它到来的数据块做一些事情。 (是的!就像 Chat GPT 之类的一样。)

即使 v0 是处理这个问题最糟糕的方法,但通过使用流可以大大改善它。即使总等待时间相同,您也可以通过显示某些内容来欺骗用户。

再次是 v5 - v1,但是带有流!

http/1 问题仍然是一个问题,但同样,您已经可以看到事情的来龙去脉。

是的…我不能再拖延了…所以…

v6 - 一个 API 来统治它们!

或者……也许我可以?

你看,前端必须管理太多......如果我们可以将其卸载到后端,那么您就可以拥有一个端点来处理所有源。

这解决了前端的复杂性和 http/1 问题。

await Promise.all([
  fetch1().then(handleResult),
  fetch2().then(handleResult),
  ...
  fetch9().then(handleResult),
]);
登录后复制


// usually we do this:
await fetch(...).then((res) => {
  // this json call accumulate all the response
  // that later is returned for you to use
  return res.json()
})
登录后复制

v7 - 最后......一个 API、多个源和流媒体。

我们调用一个 API,它将调用所有源、流式传输数据、处理数据,并将其传递到前端,而前端又会在数据到来时呈现数据。

用于此的代码正面和背面基本相同:

await fetchAll();
handleAllResults(results);
登录后复制

是的……就是这样(最基本、最简单的例子)。

我们将字符串添加到缓冲区中,解析它,检查是否有可用的块,使用它,然后忘记它。这意味着您可以接收/消耗 TB 级的数据……一次一大块,而 RAM 很少。

我知道你在想什么......这很愚蠢......这也是疯狂......

MOOOOOOOOM 我想要 Websocket!

不,亲爱的,我们家里有网络套接字!

家里的 Websocket:下一个?

v8 - 如果它不起作用,那才是愚蠢的

你很聪明,你认为如果源仍在生成数据......那么也许我们可以更新一些变量......

通过这种方式,您可以保持一个连接用于获取更多数据或更改其生成的内容。

是的......我想你可以做到这一点......并且在你的坚持下我做了这个例子。 =D

仍然......这是一个愚蠢的想法,我不知道它在哪里/是否可以在真实的生产环境中使用。也许如果你回到 MPA 和 Ajax 之间那个尴尬的 JS 阶段,在这个阶段你有足够的交互性,但没有足够的连接到同一服务器(某些浏览器的限制只有 2 个!),那么也许?

除此之外,不知道。如果您确实有……请告诉我。

在上面的例子中,注意中间的面板,尤其是“进度边框”:你可以看到它在不断更新。如果您打开网络选项卡,您会看到 GET 连接在结束之前从未关闭。您还会看到多个其他请求,这些请求改变了那个仍然存在的连接正在执行的操作……所有这些都使用普通的 http/1。

接下来是什么?

字符串与 JSON

这个例子是我能做的最基本的例子。我什至使用简单的字符串而不是 JSON,因为它更容易解析。

要使用 JSON,您必须累积字符串(出于某种原因,我们必须对后端响应进行 JSON.stringify)。

然后检查在哪里打破它,然后解析该值或边解析边解析。

对于第一个,请考虑 NDJSON:而不是 JSON 数组,您可以用换行符分隔对象,然后您可以“更轻松地”找到中断的位置,然后 JSON.parse 每个对象并使用该对象。

对于后者,你可以边解析边解析:你知道你在一个数组中,现在它是一个对象,好的第一个键,现在它是键的值,下一个键,跳过那个,下一个键......等等……手动制作并不是一件简单的事情,但这就像在等待时从等待然后渲染到渲染的跳转,这一切都是关于……除了……规模更小。

错误处理

人们喜欢托管示例,这个您需要自己运行...我希望现在不将示例托管在某个地方的原因已经清楚,但另一个原因是我们不希望这里出现任何错误,如果您要这样做的话添加网络错误高于一切......好吧......

应该处理错误,但它们确实增加了另一层复杂性。

你应该使用它吗?

也许...你可以说取决于...

有些地方流式传输是答案,但在大多数情况下......await json 就足够了(更不用说更容易了)。

但是学习流可以解决一些问题,无论是在前端还是后端。

在前端,你总是可以用它来“欺骗”用户。您可以在某些内容出现时显示它,然后在出现时显示更多内容,而不是到处显示旋转器,即使这需要一段时间。只要您不阻止用户与其交互...您甚至可以制作比仅显示旋转器“更慢”的东西感觉就像它比任何东西都快实际上更快.

在后端,您可以节省 RAM,因为您可以解析每个数据块,无论是来自前端、数据库还是中间的任何其他数据。根据需要处理数据并发送数据,而不必等待整个有效负载,否则会引发 OOM(内存不足)错误。 GB 甚至 TB 的数据……当然,为什么不呢?

尾奏

React 慢吗?整个示例前端是用 React 完成的,除了所有闪烁的“灯”发生的“主要”事情之外,还有很多其他事情发生。

是的......如果你走得足够快,示例就无法跟上并开始冻结。但由于每分钟很容易进行数千个渲染……我确实认为这对于大多数应用程序来说已经足够了。

并且,您始终可以提高性能:对于“进度边框”,如果您需要在渲染中保存一些内容,我使用了延迟值来使其更加平滑......我可以为“灯光”完成此操作以及其他性能增强和标题,但它只会让“灯”在很多时候停止闪烁(这不会成为一个很好的演示),而且标题中的“电动”下划线也不会那么有趣是。

在这个例子中,所有这些“改进”都不是理想的,但对于正常的应用程序......你可以让它处理很多事情。如果您确实需要更多东西,那么在这种情况下请使用其他解决方案。

结论

将流添加到您的武器库中......它可能不是万能的解决方案,但有一天它肯定会派上用场。

如果你想用它做点什么并且需要帮助,那么……也许可以给我打电话。 =P

以上是Chunk-Busters:不要跨越溪流!的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1667
14
CakePHP 教程
1426
52
Laravel 教程
1328
25
PHP教程
1273
29
C# 教程
1255
24
JavaScript引擎:比较实施 JavaScript引擎:比较实施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

从C/C到JavaScript:所有工作方式 从C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在行动中:现实世界中的示例和项目 JavaScript在行动中:现实世界中的示例和项目 Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

了解JavaScript引擎:实施详细信息 了解JavaScript引擎:实施详细信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:社区,图书馆和资源 Python vs. JavaScript:社区,图书馆和资源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python vs. JavaScript:开发环境和工具 Python vs. JavaScript:开发环境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

See all articles