Как я могу разрешить только наблюдаемую в редуксе epi c для продолжения только тогда, когда другой epi c не запущен - PullRequest
0 голосов
/ 17 апреля 2020

В основном мне нужны эпические сюжеты:

  1. Epi c A - Когда приходит REQUEST_A, выдает действие EPIC_A_STARTED, после некоторого неопределенного времени (асинхронное действие c), выдает действие EPIC_A_END
  2. Epi c B - Когда приходит REQUEST_B, если Epi c A не началось, продолжайте, иначе дождитесь завершения EPIC_A_END.

В идеале оба эпика при запуске будут ждать для их альтернативы завершить, так что только один происходит за один раз.

Такое ощущение, что мне нужен счетчик для увеличения при возникновении EPIC_A_STARTED и уменьшения при возникновении EPIC_A_COMPLETED, но я не совсем уверен, как действовать.

Было бы неплохо, если бы у нас был оператор, похожий на этот псевдо-код:

// Operator we are trying to write
const waitForActionsToComplete = (startAction, endAction) => {
   // Not sure how to structure this so that it waits for there to be equal of both actions passing through
}


// Epic A
const EPIC_A_FILTER = (action$, state$) =>
  action$.pipe(
    of(actions.REQUEST_A),
    waitForActionsToComplete(actions.EPIC_B_START, actions.EPIC_B_END),
    mergeMap(() => { type: actions.EPIC_A_START }));

const EPIC_A_PROCESS = (action$, state$) =>
  action$.pipe(
    of(actions.EPIC_A_START),
    ...async task,
    mergeMap(() => { type: actions.EPIC_A_END }));


// Epic B
const EPIC_B_FILTER = (action$, state$) =>
  action$.pipe(
    of(actions.REQUEST_B),
    waitForActionsToComplete(actions.EPIC_A_START, actions.EPIC_A_END),
    mergeMap(() => { type: actions.EPIC_B_START }));

const EPIC_B_PROCESS = (action$, state$) =>
  action$.pipe(
    of(actions.EPIC_B_START),
    ...async task,
    mergeMap(() => { type: actions.EPIC_B_END }));

1 Ответ

0 голосов
/ 17 апреля 2020

Вы можете использовать scan, чтобы ставить в очередь действия начала запроса, и удалять из очереди только после завершения действия epi c. Я написал что-то psuedo-codei sh:

action$.pipe(
    of(actions.REQUEST_A, actions.REQUEST_B, actions.EPIC_A_END, actions.EPIC_B_END),
    scan(({queue}, current) => {
      if (current is epic end action)
        if (queue is not empty) {
          return { queue: queue.slice(1), triggerEpic: EPIC_A_START or EPIC_B_START depending on queue[0]  }
        }
        else {
          return { queue, triggerEpic: null };
        }
      }
      else {
        if (queue is not empty) {     
          return { queue: [...queue, current], triggerEpic: null };
        }
        else {
          return { queue: [], triggerEpic: EPIC_A_START or EPIC_B_START depending on current }; 
        } 
      } 
    }, { queue: [], triggerEpic: null }),
    filter(x => x.triggerEpic !== null),
    map(x => x.triggerEpic)
)
...