Redux 同步操作
Redux 的基本用法如下所示:

Redux 异步操作
在 Redux 中, Action对象 只是一个简单的 js对象, 用于表达用户想要修改 state 的意图, Reducer 也是一个 js 纯函数, 只负责 根据 Action 对象计算 state, 不会进行 API 请求和路由跳转。那么,我们只能在发送 Action 的时候做些文章, 即对 dispatch 方法做改造, 使得 dispatch 方法可以进行 异步操作。
redux-thunk 是供 redux 使用的一个 中间件(middleware),这个中间件会对 store对象 原生的 dispatch 方法 进行包装, 然后返回一个 新的dispatch方法。 我们给这个 新的dispatch方法 传入一个函数, 即 dispatch(func), 在这个函数中我们执行 异步操作,然后在 异步操作的回调方法中执行 原生的dispatch(action) 操作, 修改 state。
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
// Action构造函数, 返回一个 Action 对象
const Action = text => {
value: text
}
// Action构建函数, 返回一个 thunk 函数
const post = () => dispatch => {
// 异步操作
setTimeout(() =>{
dispatch(Action('123'))
}, 2000)
}
// reducer
const reducer = (state, action) {
...
return state;
}
// 中间件列表
const middle = [thunk]
// 构建 Store 对象, 并应用中间件
const store = createStore(reducer, applyMiddleware(...middle))
// 同步操作
store.dispatch(Action('123'));
// 异步操作
store.dispatch(post())
Redux 异步解析
redux-thunk:
// redux 通过 applyMiddleware 使用 redux-thunk时, 会先执行 createThunkMiddleware 方法
// 传入 redux 原生的 dispatch、 getState 方法
// 或者传入上一个中间件包装以后的 dispatch、getState
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
// 如果action是函数,即thunk函数, 直接执行thunk函数
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
// 如果acton不是函数, 调用原生的dispatch方法派发Action, 修改state
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk
applyMiddleware:
export default function applyMiddleware(...middlewares) {
// 返回enhancer, createStore => createStore
return (createStore) => (reducer, preloadedState, enhancer) => {
// 执行 redux 原生的 createStore 方法,构建一个 store 对象
const store = createStore(reducer, preloadedState, enhancer)
// 原生的 dispatch 方法
let dispatch = store.dispatch
let chain = []
const middlewareAPI = {
getState: store.getState,
// 包装以后的 dispatch 方法
dispatch: (action) => dispatch(action)
}
// [chainA, chainB, chainC, chainD], 格式为 next => action
chain = middlewares.map(middleware => middleware(middlewareAPI))
// 先通过 compose 方法处理 chain,结果为 chainA(chainB(chainC(chainD(store.dispatch))))
// dispatch 是包装以后的dispatch方法
dispatch = compose(...chain)(store.dispatch)
// 返回一个新的Store对象, dispatch方法被重新包装
return {
...store,
dispatch
}
}
}
通过 applyMiddleware方法 和 thunk 中间件, store 对象的原生 dispatch 方法会被包装成如下形式:
// 包装后的 dispatch 方法
function (action) {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return dispatch(action);
}
store.dispatch(Action('123')), 我们调用的是 包装后的 dispatch方法, 因为 Action('123') 返回的是 对象即不是函数, 所以 新的dispatch方法 会直接 调用 store 原生的 dispatch 方法,然后 派发 Action, 触发 state 的修改。
store.dispatch(post()), 我们调用的同样是 包装后的dispatch方法, post() 返回的是 函数即 thunk 函数, 所以 thunk函数 会自动执行。在 thunk函数 中, 我们可以执行 异步操作, 然后在 异步操作 的 回调方法 中调用 store 的原生 dispatch 方法, 派发 Action, 触发 state 的修改。
总结一下, Redux 的异步操作流程如下:
