RX JS цепной подписки анти-шаблон с NGRX - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть следующий код, который работает, но я читал, что цепочка подписок является анти-паттерном. Мне нужно убедиться, что у пользователя есть состояние входа в систему true, прежде чем вызывать API, который требует авторизации пользователей.

Как правильно обращаться с этим в RX JS?

const subscrAuth = this.store
  .pipe(select(isLoggedIn))
  .subscribe(isLoggedIn => {
    console.log(isLoggedIn);
    if (isLoggedIn) {
      const subscrLoaded = this.store
        .pipe(select(hasCarriersLoaded))
        .subscribe(hasCarrierLoaded => {
          if (!hasCarrierLoaded) {
            this.store.dispatch(new CarriersPageRequested());
          }
        });
    }
  });
this.unsubscribe.push(subscrAuth);

Ответы [ 2 ]

2 голосов
/ 20 апреля 2020

Если это просто вызов API, вам не нужно отписываться, потому что он завершается сам по себе. Вы можете использовать switchMap для цепочки и filter для .. фильтра :). И у вас есть хорошая цепочка операторов rx js, которая самостоятельно завершает

this.store.pipe(
  select(isLoggedIn),
  take(1),
  filter((isLoggedIn) => isLoggedIn),
  switchMapTo(this.store),
  select(hasCarriersLoaded),
  take(1),
  filter((hasCarriersLoaded) => !hasCarriersLoaded),
).subscribe(() => this.store.dispatch(new CarriersPageRequested()));

Такое ощущение, что вы можете комбинировать два выбора:

combineLatest([
  this.store.pipe(select(isLoggedIn)),
  this.store.pipe(select(hasCarriersLoaded))
]).pipe(
  take(1),
  filter(([loggedIn, hasCarriers]) => loggedIn && !hasCarriers)
).subscribe(() => this.store.dispatch(new CarriersPageRequested()));

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

combineLatest([
  this.store.pipe(select(hasCarriersLoaded)),
  this.store.pipe(
    select(isLoggedIn),
    filter((loggedIn) => loggedIn)
  )
]).pipe(
  take(1),
  filter(([hasCarriers]) => !hasCarriers)
).subscribe(() => this.store.dispatch(new CarriersPageRequested()));

Если вам также нужно подождать, чтобы войти в систему, чтобы вызвать hasCarriersLoaded, вам следует переключить filter с take(1) в первом примере

2 голосов
/ 20 апреля 2020

Что-то вроде этого?

const subscrAuth = this.store
.pipe(
  select(isLoggedIn),
  switchMap(isLoggedIn => {
    this.store.pipe(
      select(hasCarriersLoaded),
      tap(hasCarriersLoaded => {
        this.store.dispatch(new CarriersPageRequested());
      })
     )
  })
).subscribe();
this.unsubscribe.push(subscrAuth);

Я бы также рекомендовал использовать функцию ngOnDestroy для управления своими подписками, например,

onDestroy$: Subject<null> = new Subject();

ngOnDestroy() {
    this.onDestroy$.next();
}

this.store
.pipe(
  takeUntil(this.onDestroy$),
  select(isLoggedIn),
  switchMap(isLoggedIn => {
    this.store.pipe(
      select(hasCarriersLoaded),
      tap(hasCarriersLoaded => {
        this.store.dispatch(new CarriersPageRequested());
      })
     )
  })
).subscribe();

или, если вы только собираетесь сделав один вызов, вы также можете изменить канал так:

this.store
.pipe(
  take(1),
  select(isLoggedIn),
  switchMap(isLoggedIn => {
    this.store.pipe(
      select(hasCarriersLoaded),
      tap(hasCarriersLoaded => {
        this.store.dispatch(new CarriersPageRequested());
      })
     )
  })
).subscribe();
...