applyMiddleware 源码地址:node_modules/redux/src/applyMiddleware.js。
applyMiddleware 的功能是中间件,实现一些非纯函数,异步操作,或者在数据流中添加一些附属功能,比如打印日志等。
一、使用示例
import {createStore,applyMiddleware} from 'redux';
import allReducers from './allReducers';
//打印日志
function logger({ getState }) {
return (next) => (action) => {
console.log('will dispatch', action);
let returnValue = null;
if(action.type == 'add'){
setTimeout(()=>{
returnValue = next(action)
},1000)
}else {
// 调用 middleware 链中下一个 middleware 的 dispatch。
returnValue = next(action);
console.log(returnValue);
console.log('state after dispatch', getState())
}
// 一般会是 action 本身,除非
// 后面的 middleware 修改了它。
return returnValue
}
}
let store = createStore(allReducers,applyMiddleware(logger));
export default store;
以上案例就是使用 applyMiddleware 实现异步操作和记录打印日志。
二、源码解读
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args)
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
- 将 applyMiddleware 调用作为第二个参数调用 createStore。createStore 的第二个参数类型为 function 时,执行
return enhancer(createStore)(reducer, preloadedState)
。 - applyMiddleware 内部通过传过去的 createStore 获取 store。
- 将 middlewareAPI 作为参数轮循调用每一个自定义的 middleware(中间件),返回值数组赋值给 chain 变量。
- 将原先 store 的 dispatch 作为参数从右至左开始调用第一个中间件,将其结果作为参数调用第二个中间件,以此类推,直到返回最后一个中间件的调用。并将返回值赋值给 dispatch。
- 运用了中间件之后,返回全新的 store,与之前 store 的区别主要体现在重写了 dispatch 方法。