- redux-saga 是一个用于管理 Redux 应用异步操作的中间件(又称异步 action)。
- redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替 redux-thunk 中间件。
function* 函数名(参数){函数体}
1 function* init(){
2 console.log('hello saga');
3 }
使用Redux-saga:
安装 npm install --save redux-saga
引入 import { createStore,applyMiddleware,compose } from 'redux' import createSagaMiddleware from 'redux-saga' import rootSaga from './saga';
以中间件的形式使用saga
createSagaMiddleware:接受 Sagas 列表,这些 Sagas 将会通过创建的 middleware 被立即执行。redux-saga 模块的 createSagaMiddleware 工厂函数,创建一个 Saga middleware
排序Sagas:使用内置的 yield* 操作符来组合多个Sagas,使它们保持顺序
1 function* playLevelOne(getState) { ... }
2 function* playLevelTwo(getState) { ... }
3 function* playLevelThree(getState) { ... }
4 function* game(getState) {
5 const score1 = yield* playLevelOne(getState)
6 put(showScore(score1))
7 const score2 = yield* playLevelTwo(getState)
8 put(showScore(score2))
9 const score3 = yield* playLevelThree(getState)
10 put(showScore(score3))
11 }
注意,使用 yield* 将导致该 Javascript 运行环境 漫延 至整个序列。
由此产生的迭代器(来自 game())将 yield 所有来自于嵌套迭代器里的值。一个更强大的替代方案是使用更通用的中间件组合机制。
组合Sagas:直接使用yield来并行地启动一个或多个子任务。当yield一个call至Generactor,Saga将等待Generator处理结束。
使用 yield* 为组合 Sagas 提供了一种通畅的方式,但这个方法也有一些局限性:
-
你可能会想要单独测试嵌套的 Generator。这导致了一些重复的测试代码及重复执行的开销。
我们不希望执行一个嵌套的 Generator,而仅仅是想确认它是被传入正确的参数来调用。 -
更重要的是,
yield*只允许任务的顺序组合,所以一次你只能 yield* 一个 Generator。
你可以直接使用 yield 来并行地启动一个或多个子任务。当 yield 一个 call 至 Generator,Saga 将等待 Generator 处理结束,
然后以返回的值恢复执行(或错误从子任务中传播过来,则抛出异常)。
1 function* fetchPosts() {
2 yield put( actions.requestPosts() )
3 const products = yield call(fetchApi, '/products')
4 yield put( actions.receivePosts(products) )
5 }
6 function* watchFetch() {
7 while ( yield take(FETCH_POSTS) ) {
8 yield call(fetchPosts) // waits for the fetchPosts task to terminate
9 }
10 }
yield 一个队列的嵌套的 Generators,将同时启动这些子 Generators(sub-generators),并等待它们完成。
然后以所有返回的结果恢复执行:
1 function* mainSaga(getState) {
2 const results = yield [ call(task1), call(task2), ...]
3 yield put( showResults(results) )
4 }
事实上,yield Sagas 并不比 yield 其他 effects(未来的 actions,timeouts,等等)不同。
这意味着你可以使用 effect 合并器将那些 Sagas 和所有其他类型的 Effect 合并。
例如,你可能希望用户在有限的时间内完成一些游戏:
1 function* game(getState) {
2 let finished
3 while(!finished) {
4 // 必须在 60 秒内完成
5 const {score, timeout} = yield race({
6 score : call( play, getState),
7 timeout : call(delay, 60000)
8 })
9 if(!timeout) {
10 finished = true
11 yield put( showScore(score) )
12 }
13 }
14 }
这是一条小尾巴ヾ(o◕∀◕)ノヾ~
须知少日拏云志,曾许人间第一流!
浙公网安备 33010602011771号