redux-thunk

详解

用于处理异步的 action, 因为 dispatch 的默认参数只能是一个 JavaScript 对象. 如果先派发一个发送请求的 action, 在派发一个处理请求结果的 action

dispatch(sendRequestAction);
dispatch(handleResponseAction);

如果可以接收一个函数作为参数, 在函数体内进行异步操作, 并在异步完成后在派发相应的 action, 那么便能解决问题

store.dispatch(fetchNewBook(’learnRedux’));

function fetchNewBook(book) {
    return function(dispatch) {
        dispatch({
            type: 'START_ FETCH_NEW_BOOK',
            data: book
        })
        ajax({
                url( `/ some/API/$(book } . ] son ` ,
                    type POST『, data: {}
                }).then(function(bookData) {
                dispatch({
                    type: 'FETCH_NEW_BOOK_SUCCESS',
                })
            })
        }
    }
redux-thunk

实例

//from action.js
const LIKE = (id) => ({
     type: "LIKE",
     id:id
})

reqLike({id:id}).then(res =>{ dispatch(LIKE(id))})

使用后

//from action.js
const LIKE = (id) => {
    return function (dispatch,getState) {
        reqLike({id:id}).then(res =>{
            dispatch({
                type: "LIKE",
                id:id
            })
        })
    }
}

dispatch(LIKE(id))

原理解析

export default function applyMiddleware(...middlewares) {
  //这个返回函数就是enhancer
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

在 redux 源码中的 createStore 函数中, enchancer 被执行,传入参数createStore,又紧接着执行其返回的函数,传入reducer和preloadedState.

if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
    return enhancer(createStore)(reducer, preloadedState)
}

在 redux-thunk 源码中

function createThunkMiddleware(extraArgument) {
  return function (_ref) {
    var dispatch = _ref.dispatch,
        getState = _ref.getState;
    //这里返回的函数就是chain
    return function (next) {
    //这里返回的函数就是改写的dispatch
      return function (action) {
        if (typeof action === 'function') {
          return action(dispatch, getState, extraArgument);
        }

        return next(action);
      };
    };
  };
}

var thunk = createThunkMiddleware();

从源码我们可以看出,chain就是以next作为形参的匿名函数,至于compose只是不断传递每个函数的返回值给下一个执行函数,然后依次去执行它所有传入的函数而已,它源码中的注释说的很清楚:For example, compose(f, g, h) is identical to doing (...args) => f(g(h(...args))).

function (action) {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    //next为之前传入的store.dispatch,即改写前的dispatch
    return next(action);
};

redux-thunk实现了相关异步流程内聚到redux的流程中,实现middleware的功能,也便于项目的开发与维护,避免冗余代码。而实现的方式便是改写redux中的dispatch API,使其可以除PlainObject外,接受一个函数作为参数。

最后更新于

这有帮助吗?