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仓库知乎问答连接欢迎各类形式交流。

相关文章
相关标签/搜索