6

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!

Faigjaz
  • 818
  • 3
  • 15
  • 30

1 Answers1

8

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>
Sean Bright
  • 118,630
  • 17
  • 138
  • 146
Max Brodin
  • 3,903
  • 1
  • 14
  • 23
  • Thanks, that's a great idea! Im not that far into rxjs, wouldn't have noticed this anytime soon. :) Now I'd like to know whether it is possible to set different values into the Observable.interval. I want users to be able to set the interval like they want. But since the observable starts emitting data as soon as my app.component is initialized (am i right?), I not quite sure whether this is possible. – Faigjaz Aug 15 '16 at 07:34
  • 2
    @Faigjaz Take a look at this question http://stackoverflow.com/questions/34058398/change-interval-settings-of-observable-after-creation – Max Brodin Aug 15 '16 at 07:41
  • Hi @Max, i have one similiar question regarding observables , here is the link https://stackoverflow.com/questions/62615131/how-to-re-subscribe-after-unsubscribing-an-observable, can you please help me out? – Suraj Gupta Jun 28 '20 at 01:58