redux-thunk:处理异步action
下面代码点击按钮后,直接修改了按钮的文本,这个文本是个固定的值。
1 2 3 4 5 6 7 8 9
| export const CHANGE_BTN_TEXT = 'CHANGE_BTN_TEXT';
export const changeBtnText = (text) => { return { type: T.CHANGE_BTN_TEXT, payload: text }; };
|
但是在我们实际生产的过程中,很多情况都是需要去请求服务端拿到数据再修改的,这个过程是一个异步的过程。又或者需要setTimeout去做一些事情。
1 2 3 4 5 6 7 8 9 10 11 12
| const mapDispatchToProps = (dispatch) => { return { changeText: (text) => { dispatch(changeBtnText('正在加载中')); axios.get('http://test.com').then(() => { dispatch(changeBtnText('加载完毕')); }).catch(() => { dispatch(changeBtnText('加载有误')); }); } }; };
|
- 问题来了,当请求后台的过程非常快,导致加载完毕先出现,然后再展示加载中。
- 这个时候我们需要去通过store.getState获取当前状态,从而判断到底是展示正在加载中还是展示加载完毕。
- 这个过程就不能放在mapDispatchToProps中了,而需要放在中间件中,因为中间件中可以拿到store。
1 2 3 4 5 6 7 8 9
| import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import reducer from './reducers';
const store = createStore( reducer, applyMiddleware(thunk) );
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import axios from 'axios'; import * as T from './actionTypes';
export const changeBtnText = (text) => { return { type: T.CHANGE_BTN_TEXT, payload: text }; };
export const changeBtnTextAsync = (text) => { return (dispatch, getState) => { if (!getState().isLoading) { dispatch(changeBtnText('正在加载中')); } axios.get(`http://test.com/${text}`).then(() => { if (getState().isLoading) { dispatch(changeBtnText('加载完毕')); } }).catch(() => { dispatch(changeBtnText('加载有误')); }); }; };
const mapDispatchToProps = (dispatch) => { return { changeText: (text) => { dispatch(changeBtnTextAsync(text)); } }; };
|
thunk的源码超级简单:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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;
|
createThunkMiddleware加强了dispatch的功能,在dispatch一个action之前,去判断action是否是一个函数,如果是函数,那么就执行这个函数。
通过redux-thunk我们可以简单地进行异步操作,并且可以获取到各个异步操作时期状态的值。