Rx Js - Как вернуть значение уведомителя с помощью оператора takeuntil - PullRequest
2 голосов
/ 29 апреля 2020

У меня есть простой таймер Rx js, который продолжает работать до тех пор, пока уведомитель не выдаст что-то очень простое c до этого момента.

enum TimerResult = {
    COMPLETE,
    ABORTED,
    SKIPPED
};

_notifier: Subject<TimerResult> = new Subject();
notifier$: Observable<TimerResult> = this._notifier.asObservable();

simpleTimer$ = interval(1000);

startTimer(): Observable<number> <-- **here I want a timerResult** {
  return simpleTimer$.pipe(
      tap(()=>doSomethingBeautifulWhileRunning),
      takeUntil(this.notifier$)
   )

}

Чего я хотел бы добиться, так это получить значение выдается уведомителем в результате.

Мне не нужны промежуточные значения, мне нужно только знать, когда оно завершается и с каким результатом.


simpleTimer$.pipe(
   tap(()=>doSomethingBeautifulWhileRunning),
   last(),
   takeUntil(this.notifier$)
).subscribe((result)=>{
   // Here, of course, I get the last value 
   // I need instead the value coming from notifier$
});

Я перепробовал множество возможных решений с операторами Rx, но ни один из них не работал так, как ожидалось. Единственный найденный мной результат, который дает приемлемый результат (но imho очень и очень грязный), был такой:

startTimer(): Observable<TimerResult>{
    simpleTimer$.pipe(...).subscribe(); <-- fire the timer, automatically unsubscribed by takeUntil
    return this.notifier$.pipe(first());
}

Какой лучший способ получить Rx? Я надеюсь, что я достаточно ясно, любая помощь очень ценится:)

Ответы [ 3 ]

0 голосов
/ 29 апреля 2020

Я думаю, что вы можете просто merge:

simpleTimer$.pipe(
  tap(() => doSomethingBeautifulWhileRunning),
  last(),
  merge(this.notifier$.pipe(take(1)),
  takeUntil(this.notifier$),
).subscribe((result)=>{
   // Here, of course, I get the last value 
   // I need instead the value coming from notifier$
});

Однако я не уверен, что это сработает в этом порядке. Возможно, вам придется переключить merge и takeUntil.

0 голосов
/ 29 апреля 2020

Вы также можете использовать combLastest

  startTimer(): Observable<any> {
    const timer$= this.simpleTimer$.pipe(
      tap((res)=>console.log(res)),
      takeUntil(this.notifier$)
    );
    return combineLatest(timer$,this.notifier$)
  }

//and use:
this.startTimer().subscribe(([timer,action])=>{
  console.log(timer,action)
})

см. stackblitz

0 голосов
/ 29 апреля 2020

Вы можете merge уведомитель с исходным потоком и получить оттуда результат, попробуйте пример ниже.

const notifier = timer(5000).pipe(mapTo("done"));

merge(interval(1000)
  .pipe(takeUntil(notifier)),
   notifier 
  )
  .subscribe(console.log,null,
   _=>console.log('complete') 
    );
...