本篇文章更新時間:2026/02/28
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知或向一介資男的 LINE 社群反應。
如果本站內容對你有幫助,歡迎贊助支持 。
內容目錄
我們值得更好的 JavaScript Streams API:一篇深度解析與我的閱讀筆記
編輯前言:這篇文章來自 Cloudflare 的 We deserve a better streams API for JavaScript。作者提出了一套以「async iterables」為基礎的新流式處理模型,指出現行 Web Streams 的設計在現代 JavaScript 生態中已經不合時宜。對寫 Node.js、Workers、Deno、Bun 或 SSR 的人而言,這是一篇相當具有啟發性的技術深論。
核心觀點 (Key Takeaways)
- Web Streams API 的複雜度來自歷史設計決策,而不是流式處理本身的必然需求。
- 最大問題包括:過度儀式化、鎖定模型混亂、BYOB 難用不常被採用、backpressure 無效、promise 過度使用造成性能瓶頸。
- Cloudflare 提出的新模型改用 async iterable、pull-based transforms、批次 chunk、明確 backpressure 策略與 sync/async 分流,實測速度比 Web Streams 快 2x–120x。
深入解析
Web Streams 標準誕生於 2014–2016,那時 JavaScript 連 for await...of 都還不存在。這讓 API 被迫用 reader/things controller 這種現在看來十分「反語法糖」的方式來描述 streaming 行為。作者的立場並不是否定前人的努力,而是指出:時代變了,我們應該用現代 JS 規範重新檢視 streaming 的必要結構。
「這些問題不是 bug,而是當年合理決策在今日的副作用。」
以下是文中對現行 API 的幾個核心批判:
- 複雜的 ceremony:一個「把 readable stream 讀完」的操作,居然要 acquire reader、手動讀取、管理鎖、releaseLock。
- 鎖定模型容易踩雷:忘記 releaseLock() 就讓 stream 永久鎖死;管線內部也會自動取得鎖,讓行為更加難以理解。
- BYOB 幾乎無人實用:複雜、容易導致 buffer detach 問題,也不能與 async iteration 或 TransformStream 搭配。
- backpressure 名存實亡:desiredSize 是「建議」,不是「強制」。甚至 tee() 會直接導致無限制的記憶體累積。
- promise 開銷巨大:每個 read/write 都會產生大量 promise,即使用戶看不到。Transform pipeline 尤其嚴重。
- 真實世界中問題頻傳:包括 fetch body 不消耗造成 connection pool 耗盡、tee() memory cliff、TransformStream backpressure 破洞、SSR 大量 GC thrashing。
Cloudflare 的新模型如何重新定義 Streams?
作者提出的替代方案有幾個鮮明特點:
- Readable stream 就是 async iterable:不再需要 reader,語法乾淨直覺。
- Transform 採「pull」語義:不做多餘工作,不提前執行,消費者拉取多少就處理多少。
- 回傳的是批次 chunk(Uint8Array[]):一次處理多筆,減少 promise 負擔。
- backpressure 四種策略明確公開:strict、block、drop-oldest、drop-newest,避免隱性累積。
- sync/async 分離:有些 pipeline 可以完全同步,不該強制經過 async machinery。
- 更容易擴充或與現有 API 轉換:因為建立在 async iterable 上,與 Web Streams 的互轉也相對明瞭。
筆者心得與啟發
讀完原文後,我最大的感觸是:Web Streams 已經變成「被歷史遺留綁架」的 API。它太複雜、性能問題太多、異常情境太難預期,而且不同 runtime 需要大量非標準優化才能讓表現過得去。
反觀 Cloudflare 的替代模型,它重新回到一個非常純粹的問題:「stream 到底是什麼?」如果把它視為 async iterable,而 transform 是 generator,那許多傳統 Web Streams 的複雜度瞬間消失。
簡單、語意清晰、行為可預測,而且性能更好。
對於常寫 Node.js、Workers 或 SSR pipeline 的人來說,這種 pull-based + batched chunk 的模式應該會帶來非常實際的性能提升,尤其是 GC thrashing 這類常被低估的問題。在多層 transform chain 的情境下(例如壓縮、加密、序列化),新的 API 幾乎是降維打擊。
我特別喜歡作者的這句話的精神:
「我們並不是要立刻取代 Web Streams,而是要展開討論。」
以 JS 生態現狀來看,我確實認為現在是時候開始討論 Stream API 的下一個階段。Web Streams 不是壞,但它已經不再符合現代 JavaScript 的語法與性能預期。Cloudflare 的提案至少展示了一件事:更好的設計是可能的,而且是「更簡單」的設計。
如果你正深陷 Web Streams 的坑、或想了解更快更直覺的 streaming 模型,原文非常值得一讀,也值得動手試試作者放出的 reference implementation。
