React Redux 中間件思想碰見 Web Worker 的靈感(附demo)

寫在最前

原文首發於做者的知乎專欄:React Redux 中間件思想碰見 Web Worker 的靈感(附demo),感興趣的同窗能夠知乎關注,進行交流。前端

熟悉 React 技術棧的同窗,想必對 Redux 數據流框架並不陌生。其倡導的單向數據流等思想獨樹一幟,雖然樣板代碼會有必定程度上的增多,可是對於開發效率和調試效率的提升是顯著的。同時還帶來了不少諸如 「時間旅行」,「 undo/redo 」 等黑魔法。react

其實這還只是表象。若是你深刻去了解 Redux 的設計理念,探索中間件奧祕,玩轉高階 reducer 等等,迎接你的就會是另外一扇門。透過它,函數式編程思想之光傾斜如注。git

思想背景

可是隨着這個 web app 複雜度的提高,數據計算量壓力徒增,你所設計的 Reducer 變得臃腫不堪。好吧,咱們能夠拆分 Reducer 使得代碼看上去更加舒服。但是計算量呢?也許有一些「夢魘」,瓶頸般永遠沒法消除。github

冥冥之中,「各類處理計算既然註定在同一時空,那麼可否永遠平行?」web

曾幾什麼時候,你是否據說過 JS 單線程異步?據說過瀏覽器卡頓或卡死?據說過 60 fps?算法

其實一個很嚴峻的事實是:根據 60 fps 計算,每一幀留給咱們 JS 執行的時間爲 16ms(甚至更少)。那麼一旦當 Reducer 計算時間過長,必然會影響瀏覽器渲染。編程

多線程思路

關於瀏覽器主線程、render queue、event loop、call stack 等內容,本文再也不復述,由於裏面的知識徹底都夠寫一本書了。假定讀者對其有一二認知,那麼你也不難理解咱們即將登場的救星—— Web Worker!redux

咱們先來簡單認識一下 web worker:後端

2008 年 W3C 制定出第一個 HTML5 草案開始,HTML5 承載了愈來愈多嶄新的特性和功能。其中,最重要的一個即是對多線程的支持。在 HTML5 中提出了工做線程(Web Worker)的概念,而且規範出 Web Worker 的三大主要特徵:瀏覽器

  • 可以長時間運行(響應);

  • 理想的啓動性能;

  • 以及理想的內存消耗。

Work 線程能夠執行任務而不干擾用戶界面。

因而,腦洞大開,可否將咱們的 Redux Reducer 計算狀態部分放進 Worker 線程中處理呢?

答案是確定的。
那麼要如何實施呢?

咱們先來看一下經典的 Redux workflow,以下圖:

redux 流程圖

若是要接入 Web Work,那麼咱們改動流程圖以下:

redux + worker 流程圖

具體實現和一個demo

固然,有了思路,還須要在實戰中演練。

我使用 「N-皇后問題」 模擬大型計算,而且實現的 demo 中能夠任意設置 n 值,增長計算耗時。
若是你不理解此算法也沒有關係,只須要知道N-皇后問題這個算法的計算耗時很長,且和 n 值相關:n 越大,計算成本越大。

除了一個極其耗時的計算,頁面中還運行這麼幾個模塊,來實現複雜的渲染邏輯操做:

  • 一個實時每16毫秒,顯示計數(每秒增長1)的 blinker 模塊;

  • 一個定時每500毫秒,更新背景顏色的 counter 模塊;

  • 一個永久往復運動的 slider 模塊;

  • 一個每16毫秒翻轉5度的 spinner 模塊

頁面過程

這些模塊都定時頻繁地更新 dom 樣式,進行大量複雜的渲染計算。正常狀況下,因爲 JS 主線程進行N-皇后計算,這些渲染過程都將被卡頓。

同時,我設置「N-皇后問題」的 n 值,來觀察在計算時這些模塊的表現(是否卡頓)。在不開啓 Work 線程的狀況下,n 設置爲13時,有 gif 圖,左半部分:

off.gif

咱們很是清晰地看到:因爲瀏覽器 call stack 進行 n=13 的皇后問題計算,而沒法「按時」渲染,因此形成了這幾個模塊的卡頓,這些模塊都沒法更新狀態。在這個卡頓過程當中,用戶的任何事件(如點擊,敲鍵盤等)都沒法被瀏覽器響應。這就是用戶體會到的「慢」!

若是我把 n 值設置的大與13呢,好比24?
千萬不要這麼作!由於你的瀏覽器會被卡死!我使用 Mac Pro 8G 內存狀況下,設置到14,瀏覽器就沒法響應了。

在開啓 Work 線程時,請參考上 gif 圖右半部分,幾個模塊的渲染絲絕不受影響。完美達到了咱們的目的。

由於 Reducer 的超級耗時計算被放入 Worker 線程當中,因此絲毫沒有影響瀏覽器的渲染和響應。徹底解決了用戶以爲「電腦慢」的問題。

看到了如此完美的對比,也許你想問 Web Worker 的兼容性如何呢?

兼容性

總結

其實,這篇文章的意義並不在於這個 demo 和應用。而是在啓發一種新的想法的同時,review 了不少 JS 當中關鍵概念和基本知識。好比:單線程異步、宿主環境、60 fps、一個算法等等。

更值得一提的是,若是你去深刻 demo 代碼,你更會發現 Redux 設計精妙的思想,好比咱們將 Web Worker 的應用抽象出一個公共庫:Redux-Worker,幷包裝爲 Redux 的中間件(middleware),全部 React Redux 均可以無侵入,採用中間件的思想使用:

import { applyWorker } from 'redux-worker';
const enhancerWithWorker = compose(
    applyMiddleware(thunk, logger),
    applyWorker(worker)
);

const store = createStore(rootReducer, {}, enhancerWithWorker);

固然,Redux-Worker 這個中間件的實現原理更是巧妙,這裏再也不展開。感興趣的同窗能夠參考個人此項目 Github 倉庫。我 fork 了此庫源碼,並在核心邏輯加入了中文註釋,感興趣的同窗能夠關注。

個人其餘關於 React 文章:

Happy Coding!

PS:
做者Github倉庫知乎問答連接歡迎各類形式交流。

相關文章
相關標籤/搜索