react系列(六)Redux Saga

在Redux中常要管理異步操做,目前社區流行的有Redux-Saga、Redux-thunk等。在管理複雜應用時,推薦使用Redux-Saga,它提供了用 generator 書寫類同步代碼的能力。
在講解 ReduxSaga 前,先要說明一下 Redux Middleware 的概念。javascript

Middleware

它提供的是位於 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-Middlewareapi

使用Redux Saga

先定一個小目標,寫一個異步增長的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);

經常使用API說明

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步。

  1. 建立saga而且將使用takeEvery給每個符合patternaction都增長一個對應的saga處理函數。
  2. 使用all導出編寫的saga。
  3. 建立saga中間件,在使用redux建立store時,應用saga中間件。
  4. 運行中間件。

感謝閱讀。

相關文章
相關標籤/搜索