Federico Rimembrana
Federico Rimembrana

Reputation: 53

RxJs - How to return notifier value with takeuntil operator

I have a simple Rxjs timer that keeps going until a notifier emits something, very basic till here.

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$)
   )

}

What I'd like to achieve is to get the value emitted by notifier as a result.

I don't need intermediate values , I need only to know when it completes and with what result.


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$
});

I tried a lot of possible solutions with Rx operators but none of them worked as expected. The only one I found that produces an acceptable result (but imho very very dirty) was this:

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

What's the best "Rx" way to obtain this? I hope I have been clear enough, any help is super appreciated :)

Upvotes: 5

Views: 3094

Answers (3)

Eliseo
Eliseo

Reputation: 58039

You can also use combineLastest

  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)
})

see stackblitz

Upvotes: 1

martin
martin

Reputation: 96969

I think you can just 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$
});

I'm not sure it's going to work in this order however. Maybe you'll have to switch merge and takeUntil.

Upvotes: 0

Fan Cheung
Fan Cheung

Reputation: 11380

You can merge the notifier with the original stream and get the result from there try the example below.

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

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

Upvotes: 1

Related Questions