Как отписаться внутри подписки rxjs, когда будет выполнено условие

ts:

import {interval, of, Subscription, Observable, takeUntil} from 'rxjs';

private statusSubscription: Subscription;

ngOnInit() {
  this.infoSubscription = interval(1000)
    .pipe(switchMap(() => this.service.getInfo()),takeUntil(res => res.body.message === 'End')
    .subscribe((res) => {
          console.log(res.body.message)
          if (res.body.message === 'End'){
             console.log('Конец')}
    })
}

Данный способ вообще ничего не выполняет. Либо использовать takeWhile(res => res.body.message !== 'End') Но он отписывается, и не выводит в консоль последнее значение перед отпиской.


Ответы (1 шт):

Автор решения: Nikolya Shirshov
  1. В первом случае ничего не происходит т.к. takeUntil должен принимать Observable, а не callback.
  2. Во втором случае вы не получаете значение в next callback, т.к. Observable завершается (complete), не доходя до next. Если у вас версия RxJs выше v6.4, можете передать в оператор takeWhile вторым аргументом true, тогда последнее значение будет передано в next.

Вы можете отписаться внутри subscribe next callback при необходимом условии.

Пример 1:

ngOnInit() {
  this.infoSubscription = interval(1000)
    .pipe(switchMap(() => this.service.getInfo()))
    .subscribe((res) => {
      if (res.body.message === 'End'){
        this.infoSubscription.unsubscribe();
      }
    })
}

Пример 2 (takeUntil):

unsubscribe$: Subject<void> = new Subject();

ngOnInit() {
  interval(1000)
    .pipe(
      switchMap(() => this.service.getInfo()),
      takeUntil(this.unsubscribe$)
    )
    .subscribe((res) => {
      if (res.body.message === 'End'){
        this.unsubscribe$.next();
        this.unsubscribe$.complete();
      }
    })
}

Пример 3 (takeWhile):

ngOnInit() {
  interval(1000)
    .pipe(
      switchMap(() => this.service.getInfo()),
      takeWhile((res) => res.body.message !== 'End', true)
    )
    .subscribe((res) => {
      if (res.body.message === 'End'){
        console.log('End')
      }
    })
}
→ Ссылка