Redux 的基本用法以下所示:redux
在 Redux 中, Action对象 只是一个简单的 js对象, 用于表达用户想要修改 state 的意图, Reducer 也是一个 js 纯函数, 只负责 根据 Action 对象计算 state, 不会进行 API 请求和路由跳转。那么,咱们只能在发送 Action 的时候作些文章, 即对 dispatch 方法作改造, 使得 dispatch 方法能够进行 异步操做。bash
redux-thunk 是供 redux 使用的一个 中间件(middleware),这个中间件会对 store对象 原生的 dispatch 方法 进行包装, 而后返回一个 新的dispatch方法。 咱们给这个 新的dispatch方法 传入一个函数, 即 dispatch(func), 在这个函数中咱们执行 异步操做,而后在 异步操做的回调方法中执行 原生的dispatch(action) 操做, 修改 state。app
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-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 方法会被包装成以下形式:post
// 包装后的 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 的修改。ui
store.dispatch(post()), 咱们调用的一样是 包装后的dispatch方法, post() 返回的是 函数即 thunk 函数, 因此 thunk函数 会自动执行。在 thunk函数 中, 咱们能够执行 异步操做, 而后在 异步操做 的 回调方法 中调用 store 的原生 dispatch 方法, 派发 Action, 触发 state 的修改。spa
总结一下, Redux 的异步操做流程以下:3d