【源码学习】redux-thunk
阅读 redux 源码之后,想要加深一下对中间件的理解,于是选择 redux-thunk(2.3.0)这个源码只有十几行的中间件。
之前 redux 的学习笔记 https://www.cnblogs.com/wenruo/p/9664375.html
redux 中的 applyMiddleware.js
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 } } }
每个中间件需要传入 store(只有 getState 和 dispatch)和 next(由上一个中间处理过的 dispatch)
在生成 dispatch 的时候 传入的 middlewareAPI 中的 dispatch 是一个只抛出异常的函数,用来提示在创建 dispatch 的时候, 中间件不应该使用 dispatch 。
创建后又将 dispatch 赋值为经过中间件生成的函数。这时
const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) }
中 middlewareAPI.dispatch 就变成了最新的 dispatch 所以在中间件中可以使用 dispatch、
接下来可以看 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;
使用时可以是 applyMiddleware(thunk) 或者 applyMiddleware(thunk.withExtraArgument(api))
如果是默认的 thunk 那么中间件的函数为
const thunk = ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState); } return next(action); };
如果是函数 就传入 dispatch 和 getState 否则就执行默认的 next
let store = createStore(reducer, applyMiddleware(thunk)); let action = (dispatch) => { ajax(options).then((res) => { dispatch({ type: 'change', content: res.data }); }) } store.dispatch(action);
这样对于异步的操作就可以在 redux 中使用了~