SWR 與前端數據依賴請求

原文鏈接:https://zhuanlan.zhihu.com/p/90660704 作者:shud.in

數據依賴關係其實是一個 DAG(有向無環圖)。有些數據依賴於其他,有的則無依賴性:

DAG:

對數據的請求則是對這個有向無環圖的遍歷。最高效的請求方式一定是在拓撲序上儘可能地並行(每當一個數據的依賴都就緒時,立即發起請求)。

仔細想想,大部分時候(請求並不複雜時),我們都用 Promise.all 來描述這個 DAG。舉例來說:

Promise.all([fetchA(), fetchB()]).then([a, b] => fetchC(a, b))

有 A,B,C 三個資源,C 依賴 A 與 B 的結果,那麼我們偶爾會寫如上代碼。實際上描述瞭如下 DAG:

但是當依賴複雜起來……例如:

有 A,B,C,D 四個資源,C 依賴 A,D 依賴 B 與 C……最並行的寫法可能是這樣的:


(以上假設在 React 中,我們需要儘快渲染 A,B,C,D)

是不是非常頭疼(飛面神教流 React 寫法)?可以當筆試題了。

但在 SWR 中,你只需要這麼寫:

依然滿足了最大的並行性,與上面完全等價。只需要描述 DAG 中,每一個點的被指向邊即可(數據依賴)。

SWR 是如何做到這一點的呢?

這裏有一個解釋:每次渲染的時候,SWR 會試着執行 key 函數(例如 ()=> '/api/c?a=' + A.id),如果這個函數拋出異常,那麼就意味着它的依賴還沒有就緒(A === undefined),SWR 將暫停這個數據的請求。在任一數據完成加載時,由於 setState 觸發重渲染,上述 Hooks 會被重選執行一遍(再次檢查數據依賴是否就緒),然後對就緒的數據發起新的一輪請求。

(以上翻譯自 https://twitter.com/shuding_/status/1189607308931653632)

題外話

最近推特上有許多關於 fetch-as-you-render 的討論,許多人陷入了對模式本身的爭論中。

但這篇文章確實提出 fetch-as-you-render 一個非常大的優勢(儘可能避免了 waterfall)。對於 waterfall,包括 React Suspense 也沒有很好的方案建議:https://reactjs.org/docs/concurrent-mode-suspense.html#for-library-authors 。

另外對於 fetch-as-you-render 的弱勢(需要在渲染時才能開始加載數據),ZEIT 的解決辦法是配合 Next.js,對第一輪數據(無其他依賴)自動生成並插入 <link link rel=preload> 標籤,改進效果非常明顯(https://twitter.com/rauchg/status/1189277551321079810)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章