【源碼學習】redux-thunk

閱讀 redux 源碼以後,想要加深一下對中間件的理解,因而選擇 redux-thunk(2.3.0)這個源碼只有十幾行的中間件。html

以前 redux 的學習筆記 http://www.javashuo.com/article/p-vqbjvrej-ep.htmlgit

redux 中的 applyMiddleware.jsgithub

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)ajax

在生成 dispatch 的時候 傳入的  middlewareAPI 中的 dispatch 是一個只拋出異常的函數,用來提示在建立 dispatch 的時候, 中間件不該該使用 dispatch 。redux

建立後又將 dispatch 賦值爲通過中間件生成的函數。這時api

const middlewareAPI = {
    getState: store.getState,
    dispatch: (...args) => dispatch(...args)
}

中 middlewareAPI.dispatch 就變成了最新的 dispatch 因此在中間件中能夠使用 dispatch、app

 

接下來能夠看 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 中使用了~

相關文章
相關標籤/搜索