前言
在閱讀此文章前捆愁,需要你會ES6的Generator函數(shù)获搏,另外redux中間件的原理也希望你能初步了解错负。
為什么會有redux-saga
中間件用過redux-thunk业岁,也用過redux-promise-middleware项贺,原理都很簡單君躺。
thunk就是簡單的action作為函數(shù),在action進行異步操作开缎,發(fā)出新的action棕叫。
而promise只是在action中的payload作為一個promise,中間件內(nèi)部進行處理之后奕删,發(fā)出新的action俺泣。
這兩個簡單也容易理解,但是當(dāng)業(yè)務(wù)邏輯多且復(fù)雜的時候會發(fā)生什么情況呢急侥?我們的action越來越復(fù)雜砌滞,payload越來越長,當(dāng)然我們可以分離開來單獨建立文件去處理邏輯坏怪,但是實質(zhì)上還是對redux的action和reducer進行了污染贝润,讓它們變得不純粹了,action就應(yīng)該作為一個信號铝宵,而不是處理邏輯打掘,reducer里面處理要好一些,但是同樣會生出幾個多余的action類型進行處理鹏秋,而且也只能是promise尊蚁,不能做復(fù)雜的業(yè)務(wù)處理。
redux-saga將進行異步處理的邏輯剝離出來侣夷,單獨執(zhí)行横朋,利用generator實現(xiàn)異步處理。
一個計數(shù)器示例
redux-saga
- saga任務(wù)百拓,新建文件處理業(yè)務(wù)邏輯琴锭,使用generator晰甚,redux-saga提供很多函數(shù)方便處理,
put
發(fā)出action决帖,takeEvery
監(jiān)聽action厕九,takeLatest
只執(zhí)行最后一次action,call
執(zhí)行函數(shù)地回,并且可以獲取promise的數(shù)據(jù)
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的一個很好的實現(xiàn)扁远。