⚠️ 如果您有光敏性,您可能想跳过此操作。
请参阅下面的静态图片,这些灯将开始快速闪烁!
互联网如何运作?
记住标题……我们在这里讨论的是流。
我可以谈论协议、数据包、排序、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中文网其他相关文章!

javaandjavascriptaredistinctlanguages:javaisusedforenterpriseandmobileapps,while javascriptifforInteractiveWebpages.1)JavaisComcompoppored,statieldinglationallyTypted,statilly tater astrunsonjvm.2)

JavaScript核心数据类型在浏览器和Node.js中一致,但处理方式和额外类型有所不同。1)全局对象在浏览器中为window,在Node.js中为global。2)Node.js独有Buffer对象,用于处理二进制数据。3)性能和时间处理在两者间也有差异,需根据环境调整代码。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

SublimeText3汉化版
中文版,非常好用

Dreamweaver CS6
视觉化网页开发工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

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