Русский перевод Redux Saga
  • Главная страница
  • Содержание
    • Главная страница
    • 1. Введение
      • 1.1 Руководство для начинающих
      • 1.2 Предпосылки Saga
    • 2. Основные концепции
      • 2.1. Использование хелперов Saga
      • 2.2 Декларативные эффекты
      • 2.3 Отправка действий
      • 2.4 Обработка ошибок
      • 2.5 Распространёная абстрация: Эффект
    • 3. Продвинутые концепции
      • 3.1 Получение будущих действий
      • 3.2 Неблокирующие вызвы
      • 3.3 Выполнение задач параллельно
      • 3.4 Выполнение гонки между несколькими эффектами
      • 3.5 Последовательность Sagas с использованием yield*
      • 3.6 Композиция Sagas
      • 3.7 Отмена задач
      • 3.8 Модель форвка redux-saga
      • 3.9 Общие паттерны параллелизма
      • 3.10 Примеры тестирования Sagas
      • 3.11 Подключение Sagas к внешнему входу/выходу
      • 3.12 Использование каналов
      • 3.13 Шаблоны корневой саги
    • 4. Рецепты
    • 5. Внешние ресурсы
    • 6. Исправление проблем
    • 7. Глоссарий
    • 8. Справочник API
Powered by GitBook
On this page
  1. Содержание
  2. 3. Продвинутые концепции

3.6 Композиция Sagas

While using yield* provides an idiomatic way of composing Sagas, this approach has some limitations:

  • You'll likely want to test nested generators separately. This leads to some duplication in the test code as well as the overhead of the duplicated execution. We don't want to execute a nested generator but only make sure the call to it was issued with the right argument.

  • More importantly, yield* allows only for sequential composition of tasks, so you can only yield* to one generator at a time.

You can use yield to start one or more subtasks in parallel. When yielding a call to a generator, the Saga will wait for the generator to terminate before progressing, then resume with the returned value (or throws if an error propagates from the subtask).

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) // waits for the fetchPosts task to terminate
  }
}

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

In fact, yielding Sagas is no different than yielding other effects (future actions, timeouts, etc). This means you can combine those Sagas with all the other types using the effect combinators.

For example, you may want the user to finish some game in a limited amount of time:

function* game(getState) {
  let finished
  while (!finished) {
    // has to finish in 60 seconds
    const {score, timeout} = yield race({
      score: call(play, getState),
      timeout: delay(60000)
    })

    if (!timeout) {
      finished = true
      yield put(showScore(score))
    }
  }
}
Previous3.5 Последовательность Sagas с использованием yield*Next3.7 Отмена задач

Last updated 6 years ago