Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 rxJS HTTP Observable Interval - Do something while waiting

Tags:

angular

rxjs

I have the following component that is subscribing to a service:

this.nodeSummarySubscription = this.netStatusService.getNodeSummary(10000).
    subscribe(
        data => {
            this.offlineNodes = data.NodesFullyDown;
            this.filteredOfflineNodes = data.NodesFullyDown;
            this.nodesOnCellularBackup = data.NodesOn3G;
            this.offlineNodesSubject.next(this.offlineNodes);
            this.cellularNodesSubject.next(this.nodesOnCellularBackup);
            this.incidentNodesSubject.next(data.MonitoredNodes);
            this.isApiCallComplete = true;
            this.myDate = new Date();
            console.log("Refreshed at " + new Date());
        },
        error => console.log(error),
        () => console.log("Call complete")
    );

On my service which executes the HTTP call during every specified interval:

getNodeSummary(interval: number) {
        return Observable.interval(interval).flatMap(() => {
            return this.http.get(this.baseApiUrl + '/HomeApi/NodeSummary/').map(res => res.json());
        });
    }

I have two questions:

  1. Why is it that on page load, my page takes the defined interval to make the call? Is there a way to fire the HTTPcall right away the first time, and only fire it every x interval after?
  2. I want to be able to display some sort of a message on the page every time a data refresh (HTTP call after expired interval). Is there another event on the Observable that I can attach to so that I can understand when the timer expired event is triggered?
like image 277
blgrnboy Avatar asked Jul 08 '26 20:07

blgrnboy


1 Answers

1) You want to use the .timer() operator instead of the interval. First argument is first delay, second argument is the interval in which the Observable is triggered.

getNodeSummary(interval: number) {
    return Observable.timer(0, interval).flatMap(() => {
        return this.http.get(this.baseApiUrl + '/HomeApi/NodeSummary/').map(res => res.json());
    });
}

2) You should create another Subject<boolean> e.g. loading$ which you will .next(true) when you start loading, and next(false) when the call returns.

private loading$ = new Subject<boolean>();

loadData() {
  this.loading$.next(true);
  this.nodeSummarySubscription = this.netStatusService.getNodeSummary(10000).
      subscribe(
          data => {
            this.offlineNodes = data.NodesFullyDown;
            this.filteredOfflineNodes = data.NodesFullyDown;
            this.nodesOnCellularBackup = data.NodesOn3G;
            this.offlineNodesSubject.next(this.offlineNodes);
            this.cellularNodesSubject.next(this.nodesOnCellularBackup);
            this.incidentNodesSubject.next(data.MonitoredNodes);
            this.isApiCallComplete = true;
            this.myDate = new Date();
            console.log("Refreshed at " + new Date());

            this.loading$.next(false);
        },
        error => console.log(error),
        () => console.log("Call complete")
    );
}

Now you can add an alert in your template like

<div class="alert alert-default" *ngIf="loading$ | async">
   Loading
</div>

and it will be displayed if you call loadData()

like image 181
Alexander Ciesielski Avatar answered Jul 13 '26 19:07

Alexander Ciesielski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!