Angular CanDeactivateGuard: как дождаться правильного или следующего значения Obersavble?

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

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 отправить?
  • … Ждет, пока не будет выпущено следующее новое событие?

2 ответа

Решение

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

this.service
  .pipe(
    skip(1),
    filter(a => ['accept', 'decline'].includes(a))
  )

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

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

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

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

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

Это приводит к игнорированию всего, что не "принимаю" или "отклоняю".

Другие вопросы по тегам