React Redux 中间件思想遇见 Web Worker 的灵感(附demo)

写在最前

原文首发于作者的知乎专栏:React Redux 中间件思想遇见 Web Worker 的灵感(附demo),感兴趣的同学可以知乎关注,进行交流。

熟悉 React 技术栈的同学,想必对 Redux 数据流框架并不陌生。其倡导的单向数据流等思想独树一帜,虽然样板代码会有一定程度上的增多,但是对于开发效率和调试效率的提高是显著的。同时还带来了很多诸如 “时间旅行”,“ undo/redo ” 等黑魔法。

其实这还只是表象。如果你深入去了解 Redux 的设计理念,探索中间件奥秘,玩转高阶 reducer 等等,迎接你的就会是另一扇门。透过它,函数式编程思想之光倾斜如注。

思想背景

但是随着这个 web app 复杂度的提升,数据计算量压力徒增,你所设计的 Reducer 变得臃肿不堪。好吧,我们可以拆分 Reducer 使得代码看上去更加舒服。可是计算量呢?也许有一些“梦魇”,瓶颈般永远无法消除。

冥冥之中,“各种处理计算既然注定在同一时空,那么能否永远平行?”

曾几何时,你是否听说过 JS 单线程异步?听说过浏览器卡顿或卡死?听说过 60 fps?

其实一个很严峻的事实是:根据 60 fps 计算,每一帧留给我们 JS 执行的时间为 16ms(甚至更少)。那么一旦当 Reducer 计算时间过长,必然会影响浏览器渲染。

多线程思路

关于浏览器主线程、render queue、event loop、call stack 等内容,本文不再复述,因为里面的知识完全都够写一本书了。假定读者对其有一二认知,那么你也不难理解我们即将登场的救星—— Web Worker!

我们先来简单认识一下 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仓库知乎问答链接
欢迎各种形式交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容