Chunk-Busters:不要跨越溪流!
⚠️ 如果您有光敏性,您可能想跳過此操作。
請參閱下面的靜態圖片,這些燈將開始快速閃爍!
互聯網如何運作?
記住標題…我們在這裡討論的是流。
我可以談論協定、資料包、排序、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中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

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

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。
