1) Чтобы дождаться завершения нескольких call
эффектов:
yield all([
call(saga2, arg1, arg2, ...),
call(saga3, arg1, arg2, ...)
]);
2) Для отправки нескольких действий и ожидания отправки их успешных действий:
yield put(action1());
yield put(action2());
yield all([
take(ACTION_1_SUCCESS),
take(ACTION_2_SUCCESS)
]);
Редактирует ответы на комментарии
Если вы вызываете саги напрямую с помощью all
(# 1 выше), то вы можете отлавливать ошибки условно
try {
yield all([
call(saga2, arg1, arg2, ...),
call(saga3, arg1, arg2, ...)
]);
} catch (e) {
// ...
}
Но если саги put
действия, которые слушают другие саги, эта сага не получает этих исключений. Saga1
не является родителем этих саг или не привязан к ним. Он просто отправляет действия, а некоторые другие задачи в другом месте слушают и отвечают.
Чтобы Saga1
знал об ошибках в этих сагах, саги не должны выдавать ошибки, а вместо этого отправлять действие с полезной нагрузкой:
function* saga2(action) {
try {
const result = yield call(...);
yield put(action2Success(result));
} catch (e) {
yield put(action2Failure(e.message));
}
}
Сага, которая вызывает saga2
(через put(action2())
), может обрабатывать успехи и неудачи:
function* saga1(action) {
yield put(action2());
yield put(action3());
const [success, failure] = yield race([
// if this occurs first, the race will exit, and success will be truthy
all([
take(ACTION_2_SUCCESS),
take(ACTION_3_SUCCESS)
]),
// if either of these occurs first, the race will exit, and failure will be truthy
take(ACTION_2_FAILURE),
take(ACTION_3_FAILURE)
]);
if (failure) {
return;
}
// ...
}
Sagas должен обрабатывать исключения и обновлять хранилище с состоянием ошибки, а не генерировать ошибки Бросать ошибки в саги становится грязно при работе с конструкциями параллельной саги. Например, вы не можете напрямую отловить ошибку, выданную задачей fork
ed. Кроме того, использование действий для оповещения о результатах саги сохраняет хороший журнал событий в вашем магазине, на который могут реагировать другие саги / редукторы. Когда вы call
другие саги, действие, которое должно инициировать эту сагу (например, takeEvery(THE_ACTION, ...)
), не отправляется.