组合 Sagas

虽然使用 yield* 是提供组合 Sagas 的惯用方式,但这个方法也有一些局限性:

  • 你可能会想要单独测试嵌套的 Generator。这导致了一些重复的测试代码及重复执行的开销。 我们不希望执行一个嵌套的 Generator,而仅仅是想确认它是被传入正确的参数来调用。

  • 更重要的是,yield* 只允许任务的顺序组合,所以一次你只能 yield* 一个 Generator。

你可以直接使用 yield 来并行地启动一个或多个子任务。当 yield 一个 call 至 Generator,Saga 将等待 Generator 处理结束, 然后以返回的值恢复执行(或错误从子任务中传播过来,则抛出异常)。

function* fetchPosts() {
  yield put( actions.requestPosts() )
  const products = yield call(fetchApi, '/products')
  yield put( actions.receivePosts(products) )
}

function* watchFetch() {
  while ( yield take(FETCH_POSTS) ) {
    yield call(fetchPosts) // 等待 fetchPosts 完成
  }
}

yield 一个队列的嵌套的 Generators,将同时启动这些子 Generators(sub-generators),并等待它们完成。 然后以所有返回的结果恢复执行:

function* mainSaga(getState) {
  const results = yield [call(task1), call(task2), ...]
  yield put(showResults(results))
}

事实上,yield Sagas 并不比 yield 其他 effects (future actions,timeouts,等等)不同。 这意味着你可以使用 effect 合并器将那些 Sagas 和所有其他类型的 Effect 合并。

例如,你可能希望用户在有限的时间内完成一些游戏:

function* game(getState) {
  let finished
  while(!finished) {
    // 必须在 60 秒内完成
    const {score, timeout} = yield race({
      score: call( play, getState),
      timeout: call(delay, 60000)
    })

    if (!timeout) {
      finished = true
      yield put(showScore(score))
    }
  }
}

results matching ""

    No results matching ""