前言
在阅读此文章前,需要你会ES6的Generator函数,另外redux中间件的原理也希望你能初步了解。
为什么会有redux-saga
中间件用过redux-thunk,也用过redux-promise-middleware,原理都很简单。
thunk就是简单的action作为函数,在action进行异步操作,发出新的action。
而promise只是在action中的payload作为一个promise,中间件内部进行处理之后,发出新的action。
这两个简单也容易理解,但是当业务逻辑多且复杂的时候会发生什么情况呢?我们的action越来越复杂,payload越来越长,当然我们可以分离开来单独建立文件去处理逻辑,但是实质上还是对redux的action和reducer进行了污染,让它们变得不纯粹了,action就应该作为一个信号,而不是处理逻辑,reducer里面处理要好一些,但是同样会生出几个多余的action类型进行处理,而且也只能是promise,不能做复杂的业务处理。
redux-saga将进行异步处理的逻辑剥离出来,单独执行,利用generator实现异步处理。
一个计数器示例
redux-saga
- saga任务,新建文件处理业务逻辑,使用generator,redux-saga提供很多函数方便处理,
put
发出action,takeEvery
监听action,takeLatest
只执行最后一次action,call
执行函数,并且可以获取promise的数据
import {delay} from 'redux-saga'
import {put, takeEvery, all, call} from 'redux-saga/effects'
export function* hello() {
console.log('hello saga!')
}
const ajax = () => new Promise(resolve=>setTimeout(()=>resolve(99), 4000))
export function* incrementAsync() {
let data = yield call(ajax)
yield put({type: 'INCREMENT'})
}
export function* watchIncrementAsync() {
yield takeEvery('INCREMENT', ()=>console.log('+1'))
yield takeEvery('INCREMENT_ASYNC', incrementAsync)
}
export default function* rootSaga() {
yield all([
hello(),
watchIncrementAsync()
])
}
- 启动generator
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(rootSaga)
后话
antd的dva是对redux-saga的一个很好的实现。