Long Polling in Angular 4

Nicolas picture Nicolas · Oct 13, 2017 · Viewed 10k times · Source

I need to do API calls to display the progress of something.

I have created a service which does this every 1.5 seconds

Main Component

private getProgress() {
        this.progressService.getExportProgress(this.type, this.details.RequestID);
    }

Services.ts

public getExportProgress(type: string, requestId: string) {
    Observable.interval(1500)
        .switchMap(() => this.http.get(this.apiEndpoint + "Definition/" + type + "/Progress/" + requestId))
        .map((data) => data.json().Data)
        .subscribe(
        (data) => {
            if (!data.InProgress)
                //Stop doing this api call
        },
        error => this.handleError(error));
}

The call works, but it keeps going. I want to stop doing the API call when the progress is finished (if (!data.InProgress) but I'm stuck on this.

How can I correctly unsubscribe from this observable when if (!data.InProgress)?

Thanks

Answer

bygrace picture bygrace · Oct 13, 2017

You could use the takeWhile operator.

Here is the documentation: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-takeWhile

Emits values emitted by the source Observable so long as each value satisfies the given predicate, and then completes as soon as this predicate is not satisfied.

Here is a generic example: https://rxviz.com/v/yOE6Z5JA

Rx.Observable
  .interval(100)
  .takeWhile(x => x < 10)
  .subscribe(x => { console.log(x); });

Here is an example with your code:

public getExportProgress(type: string, requestId: string) {
    Observable.interval(1500)
        .switchMap(() => this.http.get(this.apiEndpoint + "Definition/" + type + "/Progress/" + requestId))
        .map((data) => data.json().Data)
        .takeWhile((data) => data.InProgress)
        .subscribe(
        (data) => {
            ...
        },
        error => this.handleError(error));
}