【源码学习】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 中使用了~

 

posted @ 2019-03-19 00:29  我不吃饼干呀  阅读(534)  评论(0编辑  收藏  举报