redux源碼——applyMiddleware
相關(guān)源碼展示
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函數(shù)源碼
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;
初始化調(diào)用部分的代碼
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中調(diào)用的代碼
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這條路上,根據(jù)middleware加入了一層一層的處理,而對于redux-thunk,其實(shí)就是將異步的action的返回替換為同步的action返回,先返回一個start的action,然后等resolve了之后,再返回一個resolve的action
step1
剝離middleware的第一層,拿redux-thunk舉例,剝離之后,應(yīng)該是這樣的
next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
step2 & step3
這兩段是為了將每個middleware再次剝離之后,然后再套起來,類似俄羅斯套娃那樣,比如兩個middleware是這樣的[thunk, logger],那么經(jīng)過這兩段代碼處理之后,thunk的next就是logger,logger的next就是原先的dispatch(store.dispatch)