blgrnboy
blgrnboy

Reputation: 5157

Angular2 rxJS HTTP Observable Interval - Do something while waiting

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?

Upvotes: 3

Views: 1635

Answers (1)

Alexander Ciesielski
Alexander Ciesielski

Reputation: 10814

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()

Upvotes: 4

Related Questions