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. 运行中间件。

感谢阅读。

相关文章
相关标签/搜索