在使用redux管理异步数据流的时候,咱们会使用中间件,以redux-thunk中间件为例,咱们作一下分析:ajax
首先是构建store,咱们须要如下代码进行揉入中间件的相似creatStore函数的构造:json
const loggerMiddleware = createLogger(); const createStoreWithMiddleware = applyMiddleware( thunkMiddleware, loggerMiddleware )(createStore); export default function configureStore(initialState) { return createStoreWithMiddleware(rootReducer, initialState); }
在这段代码中,咱们用到了 redux
applyMiddleware 函数去将中间件揉入构造store的工厂函数中,
applyMiddleware函数的源码以下所示:
import compose from './compose' 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) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
先看函数的return,咱们经过applyMiddleware构建获得的createStoreWithMiddleware函数实际上是这样一个函数
function (reducer, initialState, enhancer){ ....... return { ...store, dispatch } }
而store就是它return出来的这个对象数组
store的创建流程大体就是这样,但此时store的dispatch方法已经不是原来的dispatch,注意下面的代码:数据结构
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
这才是 applyMiddleware 方法的核心,它将每一个middleware进行处理,并存入到chain 的数组中,而后调用compose方法对chain数组进行处理,处理出来的返回值就是store的dispatch,也就是咱们在业务代码中用到的dispatchapp
接下来看一下compose方法作了什么:异步
export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg } else { const last = funcs[funcs.length - 1] const rest = funcs.slice(0, -1) return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)) } }
它经过调用数组的reduceRight方法对各个中间件进行整合函数
reduceRight方法的 第一参数是 callback(preValue,curValue) ,第二个参数是要传递给callback做为第一个参数preValue来使用的fetch
这时咱们回到applyMiddleware方法中的这段代码:jsonp
var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
由此咱们能够知道传给last(...args)的正是 store.dispatch
咱们根据官方文档能够知道中间件的通用构造以下:(箭头函数这里略过)
function middleware({dispatch, getState}) { return function (next) { return function (action) { return next(action); } } }
chain数组里面的数据结构是这样的 :[ function(next){return function(action){...}},function(next){return function(action){...}} ...]
也就是 middleware函数的里面一层 的这个函数
function (next) { return function (action) { return next(action); } }
而后再通过compose的进一步reduceRight提炼:
return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
compose就是 function(action){return next(action)}
在通过 f(composed) 还是 function(action){return next(action);} 只不过这里的next是上一个中间件的返回值,追溯源头,next其实就是 store.dispatch一路通过f(composed)这种方式将中间件的方法揉和进来的变种dispatch
因此通过揉入中间件的createStore工厂函数返回的store对象的dispatch方法,其实就是function(action){return next(action);}
而后结合实际中咱们使用redux-thunk进行异步数据操做,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; //箭头函数转变正常就是这样 function createThunkMiddleware(extraArgument) { return function({ dispatch, getState }){ return function(next){ return function(action){ if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); } } }; }
经过上面分析,咱们的store.dispatch就是这个东西
function(action){ if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }
咱们在调用异步获取数据的时候 action是这样写的:
export function fetchUri(key){ return function(dispatch){ dispatch(request("show")); return $.ajax({ url:BOOKLIST_REQ.uri, dataType:"jsonp", data:{q:key,count:BOOKLIST_REQ.count} }).done(res=>{ dispatch(receive(res)); dispatch(request("hidden")); }).fail(res=>console.error(res)); }; }
激发调取异步数据方法是 store.dispatch(fetchUrl("xxx"));
这样后面的就不用细说了,怎么执行下来就一目了然了吧
这就是整个中间件大体的工做过程,若是有什么说的不对的地方,你特么来打我呀!