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!
Remember, observables are lazy. If you don't subscribe nothing is going to happen. It's good to know that when you subscribe to an observer, each call of subscribe() will trigger it's own independent execution for that given observer. Subscribe calls are not shared among multiple subscribers to the same observable.
As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak.
Unsubscribing Manually One method we can use, is to unsubscribe manually from active subscriptions when we no longer require them. RxJS provides us with a convenient method to do this. It lives on the Subscription object and is simply called . unsubscribe() .
We can simply call the unsubscribe() method from the Subscription object returned by the subscribe() method in the ngOnDestroy() life-cycle method of the component to unsubscribe from the Observable. There is also a better way to unsubscribe from or complete Observables by using the takeUntil() operator.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With