react系列(六)Redux Saga


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

Middleware

它提供的是位於 action 被發起之后,到達 reducer 之前的擴展點。

如果寫過 Koa 或者 Express ,就會很容易理解 Middleware 的概念。
可以說,Middleware 是一種置於一個調用發起到被處理這段過程之間的函數。它可以對發起的調用進行處理,處理后直接返回,或者調用下一個中間件。
在Redux中,使用柯里化函數聲明中間件,一個簡單的例子如下:

/**
 * 記錄所有被發起的 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上

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

使用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事件。

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

動態地運行 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. 運行中間件。

感謝閱讀。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM