Generic Epic с использованием Redux-Observable

Я только начал использовать Redux-Observable. Я хочу сделать общий эпос, который запрашивает данные с сервера. Я хочу, чтобы было отклонено несколько запросов с одинаковым действием и идентификатором. Однако я не знаю, как это сделать, не создавая нескольких эпиков.

const TYPE_IFEXISTS_REQUEST = 'IFEXISTS_REQUEST';
export const IFEXISTS_REQUEST = (id, value) =>
  ({ type: TYPE_IFEXISTS_REQUEST, id, value });
export const IFEXISTS_EPIC = action$ =>
  action$
    .ofType(TYPE_IFEXISTS_REQUEST)
    .debounceTime(5000) // ERROR: debounces based on action type and not id
    .mergeMap(action =>
      fromPromise(api.get(`/api/exists/${action.id}/${action.value}`))
        .map(({ data }) => IFEXISTS_SUCCESS(action.id, data))
        .catch(() => of(IFEXISTS_FAILURE(action.id, 'Server error'))));

Как можно создать общий эпос, основанный как на действии, так и на идентификаторе?


Обновление: никогда не знал о GroupBy. Он хорошо работал с switchMap. Я использовал следующее.

action$
    .ofType(TYPE_IFEXISTS_REQUEST)
    .groupBy(action => action.id)
    .mergeMap(actionByIdGroup$ => 
        actionByIdGroup$
            .debounceTime(5000) // debounces based on action id
            .switchMap(action =>
                fromPromise(api.get(`/api/exists/${action.id}/${action.value}`))
                    .map(({ data }) => IFEXISTS_SUCCESS(action.id, data))
                    .catch(() => of(IFEXISTS_FAILURE(action.id, 'Server error')))
            );
    )

person SILENT    schedule 29.09.2017    source источник


Ответы (1)


Вы можете использовать оператор groupBy:

  action$
    .ofType(TYPE_IFEXISTS_REQUEST)
    .groupBy(action => action.id)
    .mergeMap(actionByIdGroup$ => 
        actionByIdGroup$
            .debounceTime(5000) // debounces based on action id
            .mergeMap(action =>
                fromPromise(api.get(`/api/exists/${action.id}/${action.value}`))
                    .map(({ data }) => IFEXISTS_SUCCESS(action.id, data))
                    .catch(() => of(IFEXISTS_FAILURE(action.id, 'Server error')))
            );
    )

actionByIdGroup $ - это сгруппированный наблюдаемый объект с одинаковыми идентификаторами действий. Это означает, что только действия с одинаковым идентификатором будут частью одного потока. В этом случае debounceTime будет применяться к действиям с тем же идентификатором.

person ZahiC    schedule 29.09.2017
comment
Мне всегда было интересно, как можно сделать что-то подобное, но с отменой. Не могли бы вы привести пример, если знаете, как это сделать :) - person Olle Bröms; 19.11.2020