Составление Saga-ов

Хотя использование yield* обеспечивает идиоматический способ составления Saga-ов, этот подход имеет некоторые ограничения:

  • Вероятно, вы захотите протестировать вложенные генераторы отдельно.Это приводит к некоторому дублированию в тестовом коде, а также приводит к накладным расходам на дублирующийся код. Мы не хотим выполнять вложенный генератор, а только хотим убедитесь, что он был вызван с правильным аргументом.

  • Что еще более важно, yield* принимает в качестве аргумента только последовательность тасков, поэтому вы можете передавать yield* только один генератор за раз.

Вы можете просто использовать yield, чтобы параллельно запускать одну или несколько подзадач.

При вызове генератора, Saga будет ждать завершения работы генератора перед продолжением задачи, а затем возабновится с возвращенным значением (или выбрасывает исключение, если ошибка распространяется от подзадачи).

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

Yielding to an array of nested generators will start all the sub-generators in parallel, wait for them to finish, then resume with all the results

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

На самом деле, yield Saga-ов не отличается от yield других Effect-ов (actions, таймауты, т.д.).

Например, вам может понадобавится, чтобы пользователь закончил игру в течение ограниченного периода времени:

function* game(getState) {
  let finished
  while (!finished) {
    // есть всего 60 секунд что бы закончить игру
    const {score, timeout} = yield race({
      score: call(play, getState),
      timeout: call(delay, 60000) // 60000 - 60 секунд
    })

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

results matching ""

    No results matching ""