Redux學習筆記--異步Action和Middleware

異步Actionjavascript

以前介紹的都是同步操做,Redux經過分發action處理state,全部的數據流都是同步的,若是須要一步的話怎麼辦?java

最簡單的方式就是使用同步的方式來異步,將原來同步時一個action拆分紅多個異步的action的,在異步開始前、異步請求中、異步正常返回(異常)操做分別使用同步的操做,從而模擬出一個異步操做了。es6

固然,這樣的方式是比較麻煩的,如今已經有redux-saga等插件來解決這些問題了。。web

Middlewarespring

Middleware提供的是位於 action 被髮起以後,到達 reducer 以前的擴展點。在每次分發action時,全部的Middleware都會執行。編程

Middleware相似spring中的面向切面編程的思想。本質上是註冊一系列的操做,在分發action以前鏈式執行操做。redux

理解Middlewareapp

嘗試來解讀一下middleware的實現原理。以記錄日誌爲例,咱們來一步步分析Middleware的操做。異步

  1. 首先咱們能想到的就是在dispatch action的代碼先後加上log的代碼,可是這樣的話須要在全部的dispatach語句先後加代碼,太麻煩。
  2. 那麼咱們是否是能夠封裝dispatch方法,將log的代碼加到封裝的方法裏面去。可是這種狀況下須要針對每一個action都封裝不一樣的方法來完成。
  3. 咱們也能夠直接替換dispatch方法,用咱們本身封裝的方法來代替dispatch。這樣能夠解決問題,可是新的問題又出來了,假如咱們在dispatch前出了log還須要作其餘操做怎麼辦?繼續去豐富咱們替換的方法?好像不太合適。。。
  4. 把dispatch方法當作參數

在上面的步驟三中,咱們把原生dispat方法替換了,從而無法添加多個處理操做。那麼咱們是否能夠把dispatch函數當成是參數,在每一個處理操做函數中,除了正常的操做流程外,可使用dispatch參數,最終仍然將此參數返回。函數

function logger(store) {
  return function wrapDispatchToAddLogging(next) {
    return function dispatchAndLog(action) {
      console.log('dispatching', action)
      let result = next(action)
      console.log('next state', store.getState())
      return result
    }
  }
}

  es6寫法

const logger = store => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  return result
}

const crashReporter = store => next => action => {
  try {
    return next(action)
  } catch (err) {
    console.error('Caught an exception!', err)
    Raven.captureException(err, {
      extra: {
        action,
        state: store.getState()
      }
    })
    throw err
  }
}
function applyMiddleware(store, middlewares) {
  middlewares = middlewares.slice()
  middlewares.reverse()

  let dispatch = store.dispatch
  middlewares.forEach(middleware =>
    dispatch = middleware(store)(dispatch)
  )

  return Object.assign({}, store, { dispatch })
}
相關文章
相關標籤/搜索