Reputation: 1694
Scenario:
I have a api call (this.service.checkStatus(this.movieForm.value.movie)
) which should be consumed at every 60 seconds. and between the 60 second, I need to show a 1 second counter (something like x seconds until next call
). So I'm using two timer (source$
& source2$
). But the problem with the below code is source2$
doesn't stops after a new api call, instead a new subscription is created for every 60 seconds. The old source2$
subscription is still incrementing by 1 and the new one starts with 0 and making a mess. How can I fix this?
Below is my code.
Code:
source$ = timer(0, 60000); // every 60 seconds it will emit
source2$ = timer(0, 1000); // every 1 second it will emit
...
getStatus() {
this.apiSubscription$ = this.source$.subscribe(() => {
// I need to reset this timersubscription. so that the val always starts from 0
this.timerSubscription$ = this.source2$.subscribe((val: number) => {
this.timer = 60 - val;
this.progress.nativeElement.style.width = (val / 60) * 100 + '%';
});
this.service.checkStatus(this.movieForm.value.movie)
.pipe(take(1))
.subscribe(res => {
const response: any = res;
if (!response.status) {
// do stuff 1
} else {
// do stuff 2
this.apiSubscription$.unsubscribe();
}
});
});
}
Upvotes: 0
Views: 521
Reputation: 29355
this is part of why nested subscribes are an anti pattern and should be avoided... you want to be using the proper operators that handle subscribing and unsubscribing for you:
this.apiSubscription$ = source1$.pipe(
switchMap(() => { // switchMap subscribes to new inner subscriptions and cancels previous ones
const counter$ = source2$.pipe(
tap(timer => { // tap lets you produce side effects
this.timer = 60 - timer;
this.progress.nativeElement.style.width = (timer / 60) * 100 + '%';
})
)
const status$ = this.service.checkStatus(this.movieForm.value.movie).pipe(
first(), // first is more semantic IMO
tap(response => {
if (!response.status) {
// do stuff 1
} else {
// do stuff 2
}
})
)
return combineLatest(counter$, status$); // combine observables
}),
// takeWhile will end your subscription for you if the condition is false
takeWhile(([timer, statusResponse]) => !!statusResponse.status)
).subscribe()
Upvotes: 1