Русский перевод 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. 2. Основные концепции

2.4 Обработка ошибок

In this section we'll see how to handle the failure case from the previous example. Let's suppose that our API function Api.fetch returns a Promise which gets rejected when the remote fetch fails for some reason.

We want to handle those errors inside our Saga by dispatching a PRODUCTS_REQUEST_FAILED action to the Store.

We can catch errors inside the Saga using the familiar try/catch syntax.

import Api from './path/to/api'
import { call, put } from 'redux-saga/effects'

// ...

function* fetchProducts() {
  try {
    const products = yield call(Api.fetch, '/products')
    yield put({ type: 'PRODUCTS_RECEIVED', products })
  }
  catch(error) {
    yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
  }
}

In order to test the failure case, we'll use the throw method of the Generator

import { call, put } from 'redux-saga/effects'
import Api from '...'

const iterator = fetchProducts()

// expects a call instruction
assert.deepEqual(
  iterator.next().value,
  call(Api.fetch, '/products'),
  "fetchProducts should yield an Effect call(Api.fetch, './products')"
)

// create a fake error
const error = {}

// expects a dispatch instruction
assert.deepEqual(
  iterator.throw(error).value,
  put({ type: 'PRODUCTS_REQUEST_FAILED', error }),
  "fetchProducts should yield an Effect put({ type: 'PRODUCTS_REQUEST_FAILED', error })"
)

In this case, we're passing the throw method a fake error. This will cause the Generator to break the current flow and execute the catch block.

Of course, you're not forced to handle your API errors inside try/catch blocks. You can also make your API service return a normal value with some error flag on it. For example, you can catch Promise rejections and map them to an object with an error field.

import Api from './path/to/api'
import { call, put } from 'redux-saga/effects'

function fetchProductsApi() {
  return Api.fetch('/products')
    .then(response => ({ response }))
    .catch(error => ({ error }))
}

function* fetchProducts() {
  const { response, error } = yield call(fetchProductsApi)
  if (response)
    yield put({ type: 'PRODUCTS_RECEIVED', products: response })
  else
    yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
}
Previous2.3 Отправка действийNext2.5 Распространёная абстрация: Эффект

Last updated 6 years ago