redux源码——applyMiddleware
相关源码展示
applyMiddleware源码
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
// ### step1
chain = middlewares.map(middleware => middleware(middlewareAPI))
// ### step2
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
compose函数源码
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
const last = funcs[funcs.length - 1]
const rest = funcs.slice(0, -1)
// ### step3
return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}
redux-thunk源码
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
初始化调用部分的代码
import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import reducer from './reducers'
const middleware = [ thunk ]
if (process.env.NODE_ENV !== 'production') {
middleware.push(createLogger())
}
const store = createStore(
reducer,
applyMiddleware(...middleware)
)
action中调用的代码
const fetchPosts = reddit => dispatch => {
dispatch(requestPosts(reddit))
return fetch(`https://www.reddit.com/r/${reddit}.json`)
.then(response => response.json())
.then(json => dispatch(receivePosts(reddit, json)))
}
源码分析
做了什么
就是在原先同步dispatch action这条路上,根据middleware加入了一层一层的处理,而对于redux-thunk,其实就是将异步的action的返回替换为同步的action返回,先返回一个start的action,然后等resolve了之后,再返回一个resolve的action
step1
剥离middleware的第一层,拿redux-thunk举例,剥离之后,应该是这样的
next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
step2 & step3
这两段是为了将每个middleware再次剥离之后,然后再套起来,类似俄罗斯套娃那样,比如两个middleware是这样的[thunk, logger]
,那么经过这两段代码处理之后,thunk的next就是logger,logger的next就是原先的dispatch(store.dispatch)
网友评论