1 使用
const store = createStore(
rootReducer,
applyMiddleware(
thunkMiddleware, // lets us dispatch() functions
loggerMiddleware // neat middleware that logs actions
)
)
其中applyMiddleware(...)
是一个enhancer。enhancer在redux中的作用会代理createStore方法返回具有增强效果的store.
applyMiddleware接收一系列middlewares。一个典型的middleware是长这样的:
export default function thunkMiddleware({ dispatch, getState }) {
return next => action => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
return next(action);
};
}
applyMiddleware
在接收到middleware后,会进行如下处理:
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, initialState, enhancer) => {
var store = createStore(reducer, initialState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
// 将middleware初始化,些时chain里是Array<next=>action=>doSomething>
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
重点是后面的compose
语句。compose
的实现非常简单:
export default function compose(...funcs) {
return (...args) => {
if (funcs.length === 0) {
return args[0]
}
const last = funcs[funcs.length - 1]
const rest = funcs.slice(0, -1)
return rest.reduceRight((composed, f) => f(composed), last(...args))
}
}
接收一堆参数fns,返回另一个函数。在这个函数里,将参数中的函数逐个从右到左执行,上一个执行的结果将做为下一个执行的参数。
即compose(f, g, h)(100)
相当于f(g(h(100)))
. 而对于上面的dispatch = compose(...chain)(store.dispatch)
,由于chain中的每一个函数的结构均为:
function g(next) {
return function (action) {
// do something
}
}
对于函数g
,执行g(dispatch)
相当于返回一个函数:
function (action) {
// 这个函数中,next的值为dispatch
}
因此,对于d = compose(f, g)(dispatch)
,即相当于返回了一个函数:
这个函数长的是这样的:
function f1(action) {/* 函数体中的next为g1*/}
g1
的定义是function g1(action) {/* 函数体中的next为dispatch*/}
这样通过调用d
,层层next
下去,最终就调到了dispatch了。
注:由于上面的chain = middlewares.map(middleware =>middleware(middlewareAPI))
,每一个middleware都能直接访问到store.dispatch,每个middleware都可以在任意时刻进行dispatch,之所以最后一个next被弄成了dispatch,可能只是为了让默认行为是dispatch.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。