Запуск гонки между несколькими Effect-ами
Иногда мы запускаем несколько задач параллельно, но мы не хотим ждать их всех, нам просто нужно получить победителя: первый, который вернет результат (или исключение / Promise.reject).
Effect race
запускает гонку между несколькими Effect-ами.
В следующем примере показан таск, который запускает запрос удаленной выборки и ограничивает ответ в течение 1 секунды.
import { race, take, put } from 'redux-saga/effects'
import { delay } from 'redux-saga'
function* fetchPostsWithTimeout() {
const {posts, timeout} = yield race({
posts: call(fetchApi, '/posts'),
timeout: call(delay, 1000)
})
if (posts)
put({type: 'POSTS_RECEIVED', posts})
else
put({type: 'TIMEOUT_ERROR'})
}
Еще одна полезная особенность race
состоит в том, что она автоматически отменяет Effect-ы проигравших. Например, предположим, что у нас есть две кнопки:
Первый запускает задачу в фоновом режиме, которая выполняется в бесконечном цикле
while (true)
(например, синхронизация данных с сервером каждые x секунд).После запуска фоновой задачи мы включаем вторую кнопку, которая отменяет задачу
import { race, take, put } from 'redux-saga/effects'
function* backgroundTask() {
while (true) { ... }
}
function* watchStartBackgroundTask() {
while (true) {
yield take('START_BACKGROUND_TASK')
yield race({
task: call(backgroundTask),
cancel: take('CANCEL_TASK')
})
}
}
В случае диспатча action CANCEL_TASK
, Effect race
автоматически отменяет backgroundTask
, выбрасывая в нем исключение.