'Rxjs - resubscribe to unsubscribed Observable
I'm using a Service to "ping" my server every 2.5s, returning the response time from my server. Therefore I am using observables.
I am also using angular 2 and typescript.
I now want to stop the service (unsubscribe) on button click. This works just fine! The button should be a togglebutton, so if not subscribed, subscribe and other way around. But resubscribing doesn't work!
Here is my service:
export class PingService {
pingStream: Subject<number> = new Subject<number>();
ping: number = 0;
url: string = url.href;
constructor(private _http: Http) {
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);
});
});
}
}
And here is my function on click:
toggleSubscription() {
if (this.pingService.pingStream.isUnsubscribed) {
this.pingService.pingStream.subscribe(ping => {
this.ping = ping;
NTWDATA.datasets[0].data.pop();
NTWDATA.datasets[0].data.splice(0, 0, this.ping);
})
}
else {
this.pingService.pingStream.unsubscribe();
}
}
I am subscribing to the PingService within the cunstructor of my appcomponent. The data gets displayed in a chart. When I click the button for the first time, it stops the service, no data updates anymore. When I click the next time, nothing happens, although the "this.pingService.pingStream.isUnsubscribed" returns true.
my constructor:
constructor(private location: Location,
private pingService: PingService) {
this.pingService.pingStream.subscribe(ping => {
this.ping = ping;
NTWDATA.datasets[0].data.pop();
NTWDATA.datasets[0].data.splice(0, 0, this.ping);
})
}
I am also getting an error "ObjectUnsubscribedError" when I click the button for the first time.
Any help is appreciated! Thanks!
Solution 1:[1]
Since you are using RxJS you don't have to subscribe/unsubscribe. Just consider another approach using Rx streams. The idea is to have 2 streams main
and toggle
stream, so combined they fire events only when your toggle
stream is on.
var mainStream = Rx.Observable.interval(100).map(() => '.');
var display = document.getElementById('display');
var toggle = document.getElementById('toggle');
var toggleStream = Rx.Observable
.fromEvent(toggle, 'change')
.map(e => e.target.checked);
var resultStream = toggleStream
.filter(x => x === true)
.startWith(true)
.flatMap(() => mainStream.takeUntil(toggleStream));
resultStream.subscribe(x => display.innerText += x);
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.min.js"></script>
</head>
<body>
<input type="checkbox" id="toggle" checked> Check/uncheck to start/stop
<div id="display"></div>
<script src="script.js"></script>
</body>
</html>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Sean Bright |