• redux-saga 是一个用于管理 Redux 应用异步操作的中间件(又称异步 action)。
  • redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替 redux-thunk 中间件。

 

  saga中的生成器函数: function* XXX(){...}

 

      function与函数名之间有一个星号,调用生成器函数不会执行内部的代码,而是返回一个迭代器。

 

  语法:

 

  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
      const sagaMiddleware = createSagaMiddleware();
     // createSagaMiddleware:接受 Sagas 列表,这些 Sagas 将会通过创建的 middleware 被立即执行。
       const enhancer = compose(
        applyMiddleware(thunk.withExtraArgument(100)),
        composeWithDevTools(),
        applyMiddleware(sagaMiddleware)  // 使用redux-saga 模块的 createSagaMiddleware 工厂函数,创建一个 Saga middleware
    )      
 
      const store = createStore(reducer,enhancer);

    // 运行saga配置
    sagaMiddleware.run(rootSaga);

 
    export default store;

 

排序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 }

 

posted on 2021-07-22 20:46  慕华丶  阅读(374)  评论(0)    收藏  举报