RxJS, если аргументы вызываются, когда не следует - PullRequest
0 голосов
/ 08 января 2019

Я хочу условно отправить некоторые действия, используя утилиту iif из RxJS. Проблема в том, что второй аргумент для iif вызывается, даже если тестовая функция возвращает false. Это выдает ошибку и приложение сразу падает. Я новичок в силе RxJS, поэтому я, наверное, ничего не знаю. И я использую пакет подключенного реагирующего маршрутизатора, если это имеет значение.

export const roomRouteEpic: Epic = (action$, state$) =>
  action$.ofType(LOCATION_CHANGE).pipe(
    pluck('payload'),
    mergeMap(payload =>
      iif(
        () => {
          console.log('NOT LOGGED');
          return /^\/room\/\d+$/.test(payload.location.pathname); // set as '/login'
        },
        merge(
          tap(v => console.log('NOT LOGGED TOO')),
          of(
            // following state value is immediately evaluated
            state$.value.rooms.list[payload.location.pathname.split('/')[1]]
              ? actions.rooms.initRoomEnter()
              : actions.rooms.initRoomCreate(),
          ),
          of(actions.global.setIsLoading(true)),
        ),
        empty(),
      ),
    ),
  );

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Хорошо, я нашел ответ самостоятельно. Мое решение состоит в том, чтобы полностью удалить iif и полагаться только на троичный оператор внутри mergeMap. таким образом, он не оценивается после каждого 'LOCATION_CHANGE' и просто если regExp возвращает true. Спасибо за ваш интерес.

export const roomRouteEpic: Epic = (action$, state$) =>
  action$.ofType(LOCATION_CHANGE).pipe(
    pluck<any, any>('payload'),
    mergeMap(payload =>
      /^\/room\/\d+$/.test(payload.location.pathname)
        ? of(
            state$.value.rooms.list[payload.location.pathname.split('/')[2]]
              ? actions.rooms.initRoomEnter()
              : actions.rooms.initRoomCreate(),
            actions.global.setIsLoading(true),
          )
        : EMPTY,
    ),
  );
0 голосов
/ 31 мая 2019

Немного опоздал на вечеринку, но я обнаружил, что роль iif не для выполнения одного пути над другим, а для подписки на один Observable или Другой. Тем не менее, он будет выполнять все пути кода, необходимые для получения каждого Observable.

Из этого примера ...

import { iif, of, pipe } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

const source$ = of('Hello');
const obsOne$ = (x) => {console.log(`${x} World`); return of('One')};
const obsTwo$ = (x) => {console.log(`${x}, Goodbye`); return of('Two')};

source$.pipe(
  mergeMap(v =>
    iif(
      () => v === 'Hello',
      obsOne$(v),
      obsTwo$(v)
    ))
).subscribe(console.log);

вы получите следующий вывод

Hello World
Hello, Goodbye
One

Это потому, что для получения obsOne$ нужно было напечатать Hello World. То же самое верно для obsTwo$ (за исключением того, что путь печатает Hello, Goodbye).

Однако вы заметите, что он печатает только One, а не Two. Это потому, что iif оценивается в true, таким образом, подписывается на obsOne$.

Пока ваша троичная работа - я обнаружил, что эта статья объясняет более управляемый RxJS способ достижения желаемого результата довольно приятно: https://rangle.io/blog/rxjs-where-is-the-if-else-operator/

0 голосов
/ 09 января 2019

Если вы используете оператор касания внутри наблюдаемого создания (потому что оно возвращает void), это вызовет ошибку, как показано ниже

Error: You provided 'function tapOperatorFunction(source) {
return source.lift(new DoOperator(nextOrObserver, error, complete));
}' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Удалите кран и поместите консоль в подписку ().

Я создал демонстрацию stackblitz .

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