在Redux中常要管理異步操做,目前社區流行的有Redux-Saga、Redux-thunk等。在管理複雜應用時,推薦使用Redux-Saga,它提供了用 generator 書寫類同步代碼的能力。
在講解 ReduxSaga 前,先要說明一下 Redux Middleware 的概念。javascript
它提供的是位於 action 被髮起以後,到達 reducer 以前的擴展點。html
若是寫過 Koa 或者 Express ,就會很容易理解 Middleware 的概念。
能夠說,Middleware 是一種置於一個調用發起到被處理這段過程之間的函數。它能夠對發起的調用進行處理,處理後直接返回,或者調用下一個中間件。
在Redux中,使用柯里化函數聲明中間件,一個簡單的例子以下:java
/** * 記錄全部被髮起的 action 以及產生的新的 state。 */ const logger = store => next => action => { console.group(action.type) console.info('dispatching', action) let result = next(action) console.log('next state', store.getState()) console.groupEnd(action.type) return result }
而後須要將它應用到Redux上redux
import { createStore, combineReducers, applyMiddleware } from 'redux' const todoApp = combineReducers(reducers) const store = createStore( todoApp, // applyMiddleware() 告訴 createStore() 如何處理中間件 applyMiddleware(logger, crashReporter) )
以後dispatch的每個action都會觸發log中間件。
更詳細的用法在Redux文檔裏說明得很詳細了,Redux-Middleware。api
先定一個小目標,寫一個異步增長的demo。
先來建立一個sagas.js文件,用來存放咱們的sagas。數組
import { delay } from 'redux-saga' import { put, takeEvery } from 'redux-saga/effects' export function* plusAsync() { yield delay(1000) yield put({ type: 'PLUS' }) } // 在dispatch到store而且匹配pattern的每個action上派生一個saga export function* watchPlusAsync() { yield takeEvery('PLUS_ASYNC', incrementAsync) }
在上篇例子的基礎上,增長一個按鈕,用來派發PLUS_ASYNC
事件。app
<button onClick={dispatch({type: 'PLUS_ASYNC'}}>{"plusAsync"}</button>
在使用時,常常須要將多個sagas合併成一個。異步
import { all } from 'redux-saga/effects' // ... export default function* rootSaga() { yield all([ watchPlusAsync() ]) }
最後,須要建立saga Middleware。並將中間件應用到redux上。函數
import { createStore, applyMiddleware } from "redux"; // ... // 建立一個Store const sagaMiddleware = createSagaMiddleware() const store = createStore( counter, applyMiddleware(sagaMiddleware) ) // 運行sagas sagaMiddleware.run(allSagas);
middleware.run(saga, ...args)
spa
動態地運行 saga。只能 用於在 applyMiddleware 階段 以後 執行 Saga。
takeEvery(pattern, saga, ...args)
在發起(dispatch)到 Store 而且匹配 pattern 的每個 action 上派生一個 saga。
pattern
用來匹配對應的TYPE,對應到指定的saga
處理函數上。
args
就是至關於指定給saga
的參數數組,而且takeEvery
會將action拼到最後一個參數上。
takeLatest(pattern, saga, ...args)
在發起到 Store 而且匹配 pattern 的每個 action 上派生一個 saga。並自動取消以前全部已經啓動但仍在執行中的 saga 任務。
這個函數能夠說是takeEvery
的防抖版本。
具體例子能夠查看這裏-redux_saga_example。
put(action)
建立一個 Effect 描述信息,用來命令 middleware 向 Store 發起一個 action。 這個 effect 是非阻塞型的,而且全部向下遊拋出的錯誤(例如在 reducer 中),都不會冒泡回到 saga 當中。
all
建立一個 Effect 描述信息,用來命令 middleware 並行地運行多個 Effect,並等待它們所有完成。這是與標準的 Promise#all 至關對應的 API。
更多API請查看Saga文檔。
saga
的用法比較簡單,分爲4步。
saga
而且將使用takeEvery
給每個符合pattern
的action
都增長一個對應的saga處理函數。all
導出編寫的saga。感謝閱讀。