Redux-Observable - отменить следующий запрос, если он имеет те же параметры, что и текущий, но разрешить его выполнение, когда они отличаются - PullRequest
0 голосов
/ 10 октября 2019

Я новичок в реактивном программировании. Просто пытаюсь понять наблюдаемые и операторы rxjs. У меня есть приложение react-redux, которое имеет специальное промежуточное программное обеспечение для обработки кэшированных данных и флаги isFetching. Хотя он обрабатывает только те вещи, которые мне нужны, он может быть сложным для таких вещей, как отмена или отмена. Итак, я хотел перенести это приложение на redux-observable.

Я хочу не получать тот же фильм, если он загружается в данный момент. Я просто передаю селектор selectIsFetchingMovieById(action.movieId) пользовательскому промежуточному ПО. Если он возвращает true, он ничего не передает редукторам. Но когда селектор возвращает false, он выбирает фильм, проходит либо .then, либо .catch, как и любой другой процесс извлечения данных на основе обещаний.

Но когда я использую redux-observable, isFetching состояние для данного идентификатора фильма уже true. Потому что редуктор уже получил действие ({type: FETCH_MOVIE_REQUEST, movieId: "10" }). Селектор всегда возвращает true.

Если я использую switchMap, он отменяет предыдущий запрос, даже если у него другой идентификатор фильма. exhaustMap не будет запускать следующий запрос, даже если у него другой идентификатор фильма и т. Д.

Теперь у меня есть этот эпос. Это работает для cachedData ситуации. Если в магазине уже есть фильм, он не будет продолжен. Но isFetching, основанный на movieId, все еще остается проблемой.

const fetchMovieEpic = (action$, state$) =>
  action$.pipe(
    ofType(actionTypes.FETCH_MOVIE_REQUEST),
    filter(action => {
      const cachedData = selectors.selectMovie(state$.value, action.movieId);
      return !verifyCachedData(cachedData, action.requiredFields);
    }),
    map(action => action.movieId),
    switchMap(movieId =>
      ajax.getJSON(`${BASE_API_URL}/movie/${movieId}?api_key=${api_key}`).pipe(
        map(response => normalize(response, schemas.movieSchema)),
        map(normalizedData => fetchMovieSuccess(movieId, normalizedData)),
        catchError(() => of(fetchMovieError())),
        takeUntil(
          action$.pipe(
            ofType("FETCH_MOVIE_CANCELLED"),
            filter(action => action.movieId === movieId)
          )
        )
      )
    )
  );

Как я могу использовать операторы rxjs или любой другой метод, чтобы выполнить это? Я не хочу добавлять дополнительный actionType, например FETCH_MOVIE_TOGGLE_LOADING. У меня уже есть REQUEST, SUCCESS, ERROR и CANCELLED. И много других редукторов и эпопей. Таким образом, простота использования операторов может быть хорошим вариантом:)

Спасибо!

1 Ответ

0 голосов
/ 11 октября 2019

По определению exhaustMap допустим для работы. Вероятно, вы можете отладить его, реструктурировав поток и упростив внутренний поток

exhaustMap(movieId =>ajax.getJSON(`${BASE_API_URL}/movie/${movieId}?api_key=${api_key}`).pipe(catchError(() => of(fetchMovieError()))
),

и посмотрев, сработает ли последующее действие после завершения запроса

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...