在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。感谢阅读。