要想实现一个 Redux 中间件我们必须了解 Redux 的基本实现原理。本文将从 Redux 源码入手,重点讲解 applyMiddleware 如何将中间件串联执行。只有理解了底层原理我们才可以游刃有余的写出一个 Redux 中间件。
目录
createStore 源码解读
applyMiddleware 源码解读
redux-thunk 的实现原理
如何编写一个中间件
总结
createStore 源码解读
Redux 通过 createStore 来创建一个 store 对象
要理解 applyMiddleware 的实现原理,我们要从 createStore 入手
可以看见 createStore 的三个参数依次为: reducer,preloadedState,enhancer。参见源码,如果传入了 enhance 参数且为函数,则将 createStore 传入 enhance:
也就是说,现在我们将用 enhance 来创建一个 store 对象。
applyMiddleware 源码解读
一般情况下 createStore 的第三个参数 enhance 就是 applyMiddleware
applyMiddleware 的代码只有二十多行却是本文的重点
参见 createStore 的源码可以得知:applyMiddleware 依然使用 createStore 创建了store 对象并且返回,只是改写了这个对象的 dispatch 方法。
下面我们重点来看这个被改写掉的 dispatch 方法,同时理解它和原生 dispatch 方法的区别也是本文的重点。为了更直观的了解这个过程我们先来看一个简单的中间件实现 logger middleware:
下面分两部详细探讨中间件的运行原理
1.将原生的 getState 和 dispacth 作为第一个参数传入中间件数组,获得执行完的 chain 数组
2.组合串联 middleware
compose 将所有的中间件串联起来组成新的 dispatch
compose 源码
参考我们的 logger middleware 这里的 composed 即是我们的 next 参数。
reduceRight 和 ruduce 一样,不过 reduceRight 是从数组的右端开始执行,arg 将作为 reduceRight 的初始值(这里就是 store.dispatch)。假设我们的 chain 数组为 执行完毕后 dispatch 为 ,调用这个新的 dispatch 每个中间件就能依次执行了,这里的中间件执行过程也是类似于 Koa 的中间件执行的非常经典的洋葱模型。只有最后一个中间件会触发 redux 原生的 dispatch,将这个 action 分发出去。
Redux middleware 洋葱模型
只有在最后一个中间件中才调用了 store 原生的 dispatch。
redux-thunk 的实现原理
一般而言 dispatch 只能分发一个 action 对象,但是使用了 redux-thunk 中间件我们却可以分发一个异步函数。
一个异步的 action 的示例
这里的 dispatch 仍然是改造后的 dispatch。因为传入中间件的第一个参数 store(即 middlewareApi)中的 dispatch 是一个闭包,它保存着外层函数作用域中 dispatch 的引用,所以当 diapatch 被修改后,后面调用的 dispatch 都是这个新的 dispatch(即中间件的串联),所以即使在异步 action 中调用 dispatch,中间件也会从头开始执行。
如何编写一个中间件
所以理解了以上,编写一个中间件将超级简单,只需要按照中间件编写规范
总结
深入理解 Redux 中间件的实现原理,可以让我们在日常工作中,对 Redux 数据流向更加清晰和对自己的程序更加有把握。本人水平有限,如有错误还请指出。
参考资料
《深入 Redux 技术栈》
Redux 官方文档
阮一峰 Redux 入门教程
领取专属 10元无门槛券
私享最新 技术干货