Reputation: 838
I am using a service which "pings" my server and returns the response time. I then display this in a chart.
My first approach (without being able to change intervals) was this:
Observable.interval(2500)
.subscribe((data) => {
let timeStart: number = performance.now();
this._http.get(this.url)
.subscribe((data) => {
let timeEnd: number = performance.now();
let ping: number = timeEnd - timeStart;
this.ping = ping;
this.pingStream.next(ping);
});
});
}
This gets called in my app.component cunstructor:
this.pingService.pingStream.subscribe(ping => {
this.ping = ping;
NTWDATA.datasets[0].data.pop();
NTWDATA.datasets[0].data.splice(0, 0, this.ping);
})
I'm getting the "ping" and put it into my chartdata. Works fine. Now I want to change the intervall. Therefore I created a streamintervall.ts which is only exporting a variable called INTVL. I tried to use the answer in this post : Change Intervall/settings of observable after creation
So now I'm at this state, which doesn't work. My chartdata is counting from 0 on.
observable = this.pingStream.startWith(INTVL)
.switchMap((INTVL) => { return Observable.interval(INTVL) });
constructor(private _http: Http) {
this.observable.map((data) => {
let timeStart: number = performance.now();
this._http.get(this.url)
.subscribe((data) => {
let timeEnd: number = performance.now();
let ping: number = timeEnd - timeStart;
this.ping = ping;
this.pingStream.next(ping);
});
})
In my appcomponent I have an input-textbox with a 2way binding to intvl = INTVL. I really don't know how to deal with this, because rxjs is kind of hard to get into and I am not really that experienced neither, so any detailed help would be appreciated very much.
If you need more information, tell me.
EDIT: Second approach - I am now creating a new Stream on button click with the input interval : pingservice.ts:
createNew(intvl: number) {
this.pingStream = new Subject<number>();
Observable.interval(intvl)
.subscribe((data) => {
let timeStart: number = performance.now();
this._http.get(this.url)
.subscribe((data) => {
let timeEnd: number = performance.now();
let ping: number = timeEnd - timeStart;
this.ping = ping;
this.pingStream.next(ping);
});
});
}
app.component.ts:
newSubscription() {
console.log(this.pingService.pingStream.isUnsubscribed);
if (!this.pingService.pingStream.isUnsubscribed) {
this.pingService.pingStream.unsubscribe();
}
if (this.pingService.pingStream.isUnsubscribed) {
this.pingService.createNew(this.intvl)
this.pingService.pingStream.subscribe(ping => {
this.ping = ping;
NTWDATA.datasets[0].data.pop();
NTWDATA.datasets[0].data.splice(0, 0, this.ping);
})
}
}
So, stopping the pingService works, the new Stream gets created and uses the correct intervall. Now I have another issue: When subscribing to pingStream after creating the new one, I also subscribe to every other pingStream created before (or at least I think I do), which leads into multiple streams delivering my data. 5 clicks = 5 streams. Is there a way to "destroy" those streams and create a new one after?
Upvotes: 1
Views: 1057
Reputation: 7050
One way to do it would be using a Subject
to emit the wanted interval and then use a combination of switchMap and flatMap. You can pause pinging by unsubscribing from interval$
. To resume pinging resubscribe and call setInterval
again. Or use a BehaviorSubject
.
interval$: Subject<number> = new Subject<number>();
constructor(){
this.interval$
.switchMap((int: number) => Observable //switch to Observable with new interval
.interval(int)
.flatMap(() => StreamOfPings) //execute time measurement function
)
.subscribe(res => console.log(res));
}
setInterval(newInterval: number){
this.interval$.next(newInterval);
}
Upvotes: 1