Для этого требуется 2 эпоса.
const ajaxCallerEpic = action$ => (
action$
.pipe(
ofType(AJAX_ACTION),
switchMap(({
payload,
payloadId,
}) => (
merge(
from(payload) // This is an array of items
.pipe(
mergeMap(() => (
timer(5000) // This is my AJAX call
.pipe(
switchMap(() => (
merge(
of(loadedAction),
of(
sentData(
payloadId
)
),
)
)),
)
)),
),
)
))
)
)
const ajaxResponsesEpic = action$ => (
action$
.pipe(
ofType(AJAX_ACTION),
switchMap(({
payload,
payloadId,
}) => (
action$
.pipe(
ofType(SENT_DATA_ACTION),
filter(({ id }) => (
id === payloadId
)),
bufferCount(
payload
.length
),
map(anotherAction),
)
))
)
)
Важной частью является вторая SENT_DATA_ACTION
.Я передал уникальный идентификатор, когда он вызывается, чтобы убедиться, что вы слушаете правильный.Если вы не отправите их все, он будет прослушивать, пока открыт браузер.Вы всегда можете добавить тайм-аут на внутреннего слушателя, чтобы убедиться, что он завершен.Другая проблема может возникнуть, если ajaxResponsesEpic
настроит прослушиватель action$
позже, чем когда ajaxCallerEpic
выполнит вызовы AJAX.
Это вполне может оказаться условием race
.Чтобы учесть эти проблемы, сначала нужно выполнить ajaxResponsesEpic
, чтобы он настроил прослушиватель действий и одновременно запускает вызовы AJAX после его прослушивания.
Примерно так:
const ajaxCallerEpic = action$ => (
action$
.pipe(
ofType(AJAX_READY_ACTION),
switchMap(({
payload,
payloadId,
}) => (
merge(
from(payload) // This is an array of items
.pipe(
mergeMap(() => (
timer(5000) // This is my AJAX call
.pipe(
switchMap(() => (
merge(
of(loadedAction),
of(
sentAjaxData(
payloadId
)
),
)
)),
)
)),
),
)
))
)
)
const ajaxResponsesEpic = action$ => (
action$
.pipe(
ofType(AJAX_ACTION),
switchMap(({
payload,
payloadId,
}) => (
merge(
(
action$
.pipe(
ofType(SENT_AJAX_DATA_ACTION),
filter(({ id }) => (
id === payloadId
)),
bufferCount(
payload
.length
),
map(anotherAction),
)
),
(
of(ajaxReadyAction)
),
)
))
)
)