Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long Polling in Angular 4

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

like image 492
Nicolas Avatar asked Oct 13 '17 11:10

Nicolas


People also ask

What is polling in angular?

Polling is a process by which the client continuously request data from the server without any user interaction. It is mainly used to track the long running back-end process status.

What is long polling?

Siddharth Singh. HTTP Long Polling is a technique used to push information to a client as soon as possible on the server. As a result, the server does not have to wait for the client to send a request. In Long Polling, the server does not close the connection once it receives a request from the client.


2 Answers

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));
}
like image 194
bygrace Avatar answered Oct 22 '22 05:10

bygrace


I've solved this by putting the service call in a variable, and unsubscribing from that variable when I'm done.

Here's the result:

public getExportProgress(type: string, requestId: string): any {
    let progress = Observable.interval(1500)
        .switchMap(() => this.http.get(this.apiEndpoint + "Definition/" + type + "/Progress/" + requestId))
        .map((data) => data.json().Data)
        .subscribe(
        (data) => {              
            if (!data.InProgress) {
                this.toastyCommunicationService.addSuccesResponseToast("done");
                progress.unsubscribe();
            }            
        },
        error => this.handleError(error));
}
like image 42
Nicolas Avatar answered Oct 22 '22 04:10

Nicolas