Reputation: 53
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
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
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
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