在Redux中常要管理异步操作,目前社区流行的有Redux-Saga、Redux-thunk等。在管理复杂应用时,推荐使用Redux-Saga,它提供了用 generator 书写类同步代码的能力。
在讲解 ReduxSaga 前,先要说明一下 Redux Middleware 的概念。
Middleware
如果写过 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)
takeEvery(pattern, saga, ...args)
pattern
用来匹配对应的TYPE,对应到指定的saga
处理函数上。args
就是相当于指定给saga
的参数数组,并且takeEvery
会将action拼到最后一个参数上。
takeLatest(pattern, saga, ...args)
这个函数可以说是takeEvery
的防抖版本。
具体例子可以查看这里-redux_saga_example。
put(action)
all
更多API请查看Saga文档。
总结
saga
的用法比较简单,分为4步。
- 创建
saga
并且将使用takeEvery
给每一个符合pattern
的action
都增加一个对应的saga处理函数。 - 使用
all
导出编写的saga。 - 创建saga中间件,在使用redux创建store时,应用saga中间件。
- 运行中间件。
感谢阅读。