-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
最近一直在写 React-Native 相关的东西,项目中用的是 redux 和一些中间件作为状态管理方案,于是梳理了下 redux middleware 相关的东西,简单记录一下~方式是以一个例子开始,再结合相关源码介绍一下 applyMiddleware 及 redux enhancer 的原理。
在 redux 里我们都知道 dispatch 一个 action 会到达 reducer,而 middleware 就是为我们提供 action 被发起之后,到达 reducer 之前的扩展点,比如记录日志📝,创建崩溃报告,调用异步接口等。
一般一个 middleware 的签名是这样的:
({ getState, dispatch }) => next => action => any,(这里的 any 一般是 action 本身)举个🌰,一个能在 store dispatch 时自动 logger 的 middleware 如下所示:
function logger({ getState }) {
return (next) => (action) => {
console.log('will dispatch', action)
// 调用 middleware 链中下一个 middleware 的 dispatch。
let returnValue = next(action)
console.log('state after dispatch', getState())
// 一般会是 action 本身,除非
// 后面的 middleware 修改了它。
return returnValue
}
}
const store = createStore(
todos,
[ 'Use Redux' ],
applyMiddleware(logger)
)
store.dispatch({
type: 'ADD_TODO',
text: 'Understand the middleware'
})
// (将打印如下信息:)
// will dispatch: { type: 'ADD_TODO', text: 'Understand the middleware' }
// state after dispatch: [ 'Use Redux', 'Understand the middleware' ]这个 middleware 是怎么作用到我们的 store 的呢?next 又代表着什么含义呢?
简单看下原理,applyMiddleware 内部的实现大致是这样:
// 非 applyMiddleware 源码 只不过方便理解
// @param middlewares
// @return createStore => createStore
function applyMiddleware(middlewares) {
// 返回一个 store enhancer
return (createStore) => { // store enhancer 接收一个 createStore 为参数
// 返回一个加强过的 createStore
return (...args) => {
const store = createStore(...args);
let dispatch = store.dispatch;
middlewares = middlewares.slice()
// 将 middllewares 从右向左排列
middlewares.reverse()
middlewares.forEach(middleware =>
// 重写上一个经过 middleware 的 dispatch
// 第一个 middleware 会处理 store 原始的 dispatch
dispatch = middleware(store)(dispatch)
)
// 返回经过重新组合过的 store
return Object.assign({}, store, { dispatch })
}
}
}而 applyMiddleware 最终是通过作为 createStore 时的 enhancer 来影响 store 的,enhancer 相关的源码如下,它的签名是 createStore => createStore
// redux createStore 部分源码
function createStore (reducer, preloadedState, enhancer) {
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState)
}
// some other codes
}梳理一下:
- applyMiddleware 应用 middlewares 生成 store enhancer,enhancer 是一个输入输出都是 createStore 的函数,会代替原生的 createStore 去创建我们最终的 store
- enhancer 生成的是加强过的 createStore,怎么加强的呢?可以看 applyMiddleware 返回的 enhancer 函数中返回的新 createStore,他先是利用原生的 createStore 生成一个正常的 store,并且拿到它的 dispatch 方法,然后对传入 middlewares 从右向左排列,用上一个 middleware(store)(dispatch) 生成的 dispatch 去复写 dispatch,最终的 dispatch 类似经过了这样的包装:dispatchFinal = middleware1(store) (middleware2(store)(middleware3(store)(middleware4(store)(dispatchInitial)))),然后代替原生的 dispatch 作为 store 的成员返回给调用方
- 从 2 可以看到,middleware 需要实现的功能是:利用 store 和上一个经过修饰的 dispatch 生成新的 dispatch 。在生成新的 dispatch 的过程中,我们可以加上很多功能,当然也可以干掉很多功能(直接拦截),比如我们一开始提到的 logger middleware 先是打印出 action 的内容,再调用上一个 dispatch 做了一下 action 分发(执行 next 函数),可以想象,next 里面又会去调用它的上一个 dispatch(如果没有,则是调用原生的 diaptch),等 next 的调用结束后,logger 则继续执行他的下一步:打印当前 state 的值和返回 next 函数执行的返回值。这是一个经典的”洋葱模型“。
- middleware 中的参数
next实际上可以理解为”上一个 dispatch" ,即被 applyMiddleware 包装的 “dispatch 洋葱"中,里面一层的 dispatch
备注:
- 上面的 applyMiddleware 的实现非官方实现,只是为了方便理解。源码可见:https://github.com/reduxjs/redux/blob/master/src/applyMiddleware.ts
- enhancer 是 redux 的一个很强大的扩展机制,applyMiddleware 只是 enhancer 的冰山一角,它只改变了 store dispatch 的默认行为。其他 enhancer 的例子如: redux-devtools
Reactions are currently unavailable