002 Redux middleware
CENSWIN 11/2/2021 Redux
# 什么是middleware
在Redux 中,当action发出之后,reducer立即返回新的state,这个流程是一个同步操作,如果需要异步操作的话就需要使用applyMiddleware并结合一些中间件进行拦截,当我们请求接口后获取了响应数据再将数据交给reducer来修改我们的store数据

本质上就是对 store.dispatch 进行了增强,在发出 Action和执行 Reducer这两步之间,添加了其他功能
一些常见的中间件
- redux-thunk
- redux-saga
相关用法详见异步编程
# middleware实现原理
Redux 提供了 applyMiddleware 方法来加载 middleware,该方法的源码如下
import compose from './compose';
export default function applyMiddleware(...middlewares) {
return (next) => (reducer, initialState) => {
let store = next(reducer, initialState);
let dispatch = store.dispatch;
let chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action),
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch);
return {
...store,
dispatch,
};
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
所有中间件被放进了一个数组chain,然后嵌套执行,最后执行store.dispatch。可以看到,中间件内部(middlewareAPI)可以拿到getState和dispatch这两个方法;看一下 redux-thunk 的源码
const thunk = function ({dispatch, getState}) {
return function (next) {
return function (action) {
if (typeof action === 'function') {
return action(dispatch, getState)
} else {
return next(action)
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
函数式编程思想设计
middleware 的设计有点特殊,是一个层层包裹的匿名函数,这其实是函数式编程中的 currying,它是一种使用匿名单参数函数来实现多参数函数的方法。applyMiddleware 会对 logger 这个 middleware 进行层层调用,动态地将 store 和 next 参数赋值。
另外, applyMiddleware 的结构也是一个多层 currying 的函数。借助 composeapplyMiddleware 可以用来和其他插件加强 createStore 函数:
import { createStore, applyMiddleware, compose } from 'Redux';
import rootReducer from '../reducers';
import DevTools from '../containers/DevTools';
const finalCreateStore = compose(
// 在开发环境中使用的 middleware
applyMiddleware(d1, d2, d3),
// 它会启动 Redux DevTools
DevTools.instrument()
)(createStore);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10