Angular CanDeactivateGuard: как ждать правильного или следующего значения Obersavble? - PullRequest
2 голосов
/ 09 февраля 2020

У меня есть служба, которая генерирует события:

export class MyService {
  private event = new BehaviorSubject<string>('init');
  event$ = this.event.asObservable();

  constructor() { }

  update(): void {
    this.event.next('update');
  }

  accept(): void {
    this.event.next('accept');
  }

  decline(): void {
    this.event.next('decline');
  }
}

У меня также есть CanDeactivateGuard, который вызывается функцией в компоненте:

canDeactivate(): Observable<boolean> {
  return this.service.event$.pipe(
    map(action => {
      return action === 'accept';
    })
  )
}

Теперь это работает все хорошо. Но у меня есть проблема:

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

Как я могу заставить это работать так, чтобы оно либо:

  • … ожидало пока accept или decline не будет отправлено?
  • … ждет, пока не будет отправлено следующее fre sh событие?

Ответы [ 2 ]

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

Вы можете пропустить первое излучение с вашего BehaviorSubject с помощью skip:

this.service
  .pipe(
    skip(1),
    filter(a => ['accept', 'decline'].includes(a))
  )
1 голос
/ 09 февраля 2020

Вы получаете начальные события, потому что это BehaviorSubject.

Вы получаете все события, потому что вы не отфильтровываете их.

То, как вы подходите к этому, зависит от того, для каких целей событие $ обслуживает. Если важно испустить все события, включая начальное состояние, то определенно оставьте это как субъект поведения.

Я бы отфильтровал события в охране:

canDeactivate(): Observable<boolean> {
  return this.service.event$.pipe(
    filter(action => action === 'accept' || action === 'decline'),
    map(action => {
      return action === 'accept';
    })
  );
}

Это имеет эффект игнорирования всего, что не «принять» или «отклонить».

...