Redux中间件原理
中间件主要被用于分离那些不属于你应用的核心业务逻辑的可被组合起来使用的代码。
- 不使用middleware时,在dispatch(action)时会执行Reducer,并根据action的type更新返回相应的state。
- 而在使用middleware时,简言之,middleware会将我们当前的action做相应的处理,随后再交付Reducer执行
- 通过重写dispatch方法,在派发action之前或之后添加逻辑(AOP)。 你可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。每一个 middleware 处理一个相对独立的业务需求,通过串联不同的 middleware,实现变化多样的的功能。
相关源码分析
1 | import { createStore } from 'redux'; |
代码执行过程分析
1、依次执行middleware:将middleware执行后返回的函数合并到一个chain数组,如下
const chain = middlewares.map(middleware => middleware(middlewareAPI))
1
2
3
4
5
6
7
8
9
10
11// ES6箭头函数
export default ({ dispatch, getState }) => next => action => {}
// 即
function ({ dispatch, getState }) {
return function(next) {
return function (action) {
return {}
}
}
}那么此时合并的chain结构如下
1
2
3
4
5
6
7[ ...,
function(next) {
return function (action) {
return {}
}
}
]
2、修改dispatch,增加功能:compose函数,实际就是一个柯里化函数,即将所有的middleware合并成一个middleware,并在最后一个middleware中传入当前的dispatch
- dispatch = compose(…chain)(store.dispatch) 返回重写的dispatch
执行 compose(…chain)(store.dispatch),当前 a 对应于 蓝色框 代码,b 对应于 红色框 代码 。首先会执行 红色框 对应的代码,执行后返回 黄色框 对应的代码。此时,蓝色框 中的next指向 黄色框 对应的代码。最终 蓝色框 对应的代码执行,返回 绿色框 的代码。就是重写的 dispatch 函数。
- dispatch = compose(…chain)(store.dispatch) 返回重写的dispatch
3、触发异步action,执行过程如下
1
2
3
4
5
6
7
8asyncAdd(){
//在redux中派发的动作只能是纯对象,并不能 store.dispatch 函数
return function(dispatch){
setTimeout(() => {
dispatch({type:types.ADD});
}, 1000);
}
},触发 asyncAdd,执行 绿色框* 的代码,由于当前 action 为 asyncAdd 函数中返回的函数,所有会执行 action(dispatch)。执行asyncAdd 中的函数,执行setTimeout,1秒钟之后执行 dispatch({type:types.ADD}); ,即执行 绿色框* 的代码。由于当前 action 为 对象,所有会执行 else 条件中的代码。当前,next 指向 黄色框 的代码。执行 黄色框 的代码,先打印旧状态,然后执行 next(action);,当前 next 指向原生的 dispatch 函数,会触发 action 修改 state,触发视图的更新。最后打印新状态。