Using tap
to trigger the second observable results in multiple subscriptions.
Option 1
If I understand the question correctly, you're trying to re-trigger the HTTP request after 5 seconds AFTER the current request has emitted. In that case the time interval b/n the calls is dynamic. In that case you'd try to trigger the request manually after each notification using BehaviorSubject
.
Try the following
import { timer, BehaviorSubject, Subject } from 'rxjs';
import { switchMap, takeUntil } from 'rxjs/operators';
export class Sample implements OnInit, OnDestroy {
timerSrc = new BehaviorSubject<number>(0); // <-- default time
close = new Subject<any>(); // <-- use to close open observables
ngOnInit() {
this.timerSrc.asObservable().pipe(
takeUntil(this.close),
switchMap((time: number) => timer(time)),
switchMap(() => this.httpRequest())
).subscribe({
next: (response: any) => {
// use response
this.timerSrc.next(5000); // <-- call again in 5 seconds
},
error: (error: any) => {
// handle error
}
});
}
ngOnDestroy() {
this.close.next(); // <-- close open subscription
}
}
Option 2
If you do not mind have a fixed timer of 5 seconds b/n each successive calls, you could pipe to a timer with 5 second interval using exhaustMap
. It'd ignore incoming emissions until the inner observable (the HTTP request) has emitted.
Note that here there would be no guarantee that each successive would have a fixed time interval of 5 seconds. It might be anything b/n 0 - 5 seconds depending on the time taken for the HTTP request to emit.
import { timer, Subject } from 'rxjs';
import { exhaustMap } from 'rxjs/operators';
export class Sample implements OnInit, OnDestroy {
close = new Subject<any>(); // <-- use to close open observables
ngOnInit() {
timer(0, 5000).pipe(
takeUntil(this.close),
exhaustMap(() => this.httpRequest())
).subscribe({
next: (response: any) => {
// use response
},
error: (error: any) => {
// handle error
}
});
}
ngOnDestroy() {
this.close.next(); // <-- close open subscription
}
}