Буферизация конкат карты - PullRequest
2 голосов
/ 08 января 2020

Я пытаюсь найти способ, как я могу буферизовать данные на входе concatMap до завершения предыдущего наблюдения.

Лучше объяснить это на моем реальном примере.

У меня есть приложение, использующее наблюдаемую избыточность.

Существует действие validate

const validate = updatedDataIds => ({
  type: VALIDATE,
  payload: { updatedDataIds },
});

Я хочу буферизовать массив updatedDataIds и уменьшить количество вызовов longTimePostAjaxFunction .

export const validateEpic = (action$, state$, { longTimePostAjaxFunction }) =>
  action$.pipe(
    ofType(VALIDATE),
    map(({ payload: { updatedDataIds } }) => updatedDatapointIds),
    // I want to buffer longTimePostAjaxFunction here until previous observable (longTimePostAjaxFunction) completes
    map(flatten),
    concatMap(updatedDataIds =>
      longTimePostAjaxFunction('validate/url', {
        updatedDataIds,
      }).pipe(
        map(validateFulfilled),
      ),
    ),
  );

У вас есть идеи, как мне решить эту проблему?

Ответы [ 2 ]

1 голос
/ 09 января 2020

Одним из способов решения вашей проблемы является поток, который генерируется каждый раз, когда longTimePostAjaxFunction разрешается. Например (хотя, возможно, есть и лучшие варианты), вы можете буферизовать поток идентификаторов на action$.pipe(ofType('READY_FOR_IDS') и сгладить готовое действие в поток результатов AJAX.

export const validateEpic = (action$, state$, { longTimePostAjaxFunction }) =>
  action$.pipe(
    ofType(VALIDATE),
    map(({ payload: { updatedDataIds } }) => updatedDatapointIds),
    buffer(action$.pipe(ofType('READY_FOR_IDS')),
    map(flatten),
    concatMap(updatedDataIds =>
      longTimePostAjaxFunction('validate/url', {
        updatedDataIds,
      }).pipe(
        map(validateFulfilled)
      ),
    ),
    concatMap(action => [action, { type: 'READY_FOR_IDS' }])
  );
0 голосов
/ 13 января 2020

Мое текущее (дерьмовое) решение:

буфер:

..
   map(({ payload: { updatedDataIds } }) => updatedDataIds),
        buffer(action$.pipe(ofType(VALIDATION_START))),
        map(flatten),
..    

буферизация логи c:

export const pendingValidate = action$ =>
  mergeMap(() =>
    action$.pipe(
      ofType(VALIDATE, VALIDATE_FULFILLED),
      map(({ type }) => type),
      scan(
        ([gate], currentAction) => {
          if (currentAction === VALIDATE) {
            if (gate === 'open') return ['closed', true];
            return ['waiting', false];
          }

          if (gate === 'waiting' && currentAction === VALIDATE_FULFILLED) {
            return ['closed', true];
          }

          return ['open', false];
        },
        ['open', false],
      ),
      filter(([, shouldValidate]) => shouldValidate),
      map(() => ({ type: VALIDATION_START })),
    ),
  ),
);

...