20

I have this service using HttpClient to get some data :

checkData() {
    return this.http.get('my url');
}

The on the footer component I call it and display the result :

ngOnInit() {
    this.myservice.checkdata().subscribe( result => { this.statustext = result } );
}

This works, but I need this method to be run every 10 seconds so it's up to date.

How can I do this?

Robert Hegner
  • 9,014
  • 7
  • 62
  • 98

7 Answers7

46

Try with timer from RxJS :

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription, timer } from 'rxjs';
import { switchMap } from 'rxjs/operators';

import { MyService } from 'path/to/the/service/my-service.service';

@Component({
  ......
})
export class MyExampleComponent implements OnInit, OnDestroy {
    subscription: Subscription;
    statusText: string;
    
    constructor(private myService: MyService) {}

    ngOnInit() {
        this.subscription = timer(0, 10000).pipe(
          switchMap(() => this.myService.checkdata())
        ).subscribe(result => this.statusText = result);
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}

interval(10000) from RxJS is not appropriate, because it will start to emit values ONLY after 10sec and not immediatly for the first time (and I think that's not what you're looking for).

However, timer(0, 10000), will emit values immediatly (0) and every 10sec (10000) until unsubscription.

Adrien SAULNIER
  • 1,651
  • 1
  • 13
  • 19
18

Use rxjs timer to call the api request at startup and then every 10s.

This is best achieved by using rxjs to divide and conquer.

Firstly, import the following:

import { timer, Observable, Subject } from 'rxjs';
import { switchMap, takeUntil, catchError } from 'rxjs/operators';

Then add the property to handle request to the api:

private fetchData$: Observable<string> = this.myservice.checkdata();

Next, add the property to handle the timing:

private refreshInterval$: Observable<string> = timer(0, 1000)
.pipe(
  // This kills the request if the user closes the component 
  takeUntil(this.killTrigger),
  // switchMap cancels the last request, if no response have been received since last tick
  switchMap(() => this.fetchData$),
  // catchError handles http throws 
  catchError(error => of('Error'))
);

At last, fire the kill command if the component is killed:

ngOnDestroy(){
  this.killTrigger.next();
}

Here is a StackBlitz Demo.

Rai4n
  • 15
  • 5
FAISAL
  • 33,618
  • 10
  • 97
  • 105
2

The rxjs way to do this would be the following.

import { interval } from 'rxjs/observable/interval';
import { map } from 'rxjs/operators';

const timeInterval$ = interval(10000);

timeInterval$.pipe(
  map( () => this.http.get(//some url);
);
Mike Tung
  • 4,735
  • 1
  • 17
  • 24
1

In your checkData method you could do something like this:

import { timer, of } from 'rxjs';
import { switchMap, catchError } from 'rxjs/operators';

checkData() {
    return timer(0, 10000)
        .pipe(
           switchMap(_ => this.http.get('my url')),
           catchError(error => of(`Bad request: ${error}`))
        );
}

Then your subscribe will get the result of the http call every 10 seconds.

Marc Harry
  • 2,410
  • 19
  • 21
  • This seems to work but as soon as there's an error ...ie: no internet connection or cannot find data it will stop looping –  May 29 '18 at 14:02
  • Updated with catch for the error if one occurs in the http request – Marc Harry May 29 '18 at 14:28
  • This works for a single value , but when there is a parameter passed to the http method , it is remembering all the previous values passed ang giving results for all the values passed till now , which is wrong . – Sunny Srivastava May 30 '22 at 08:12
0

Hope this will help you

export class YourComponent implements OnInit, OnDestroy {
  private alive: boolean;

  constructor(){}

  ngOnInit(){
    this.alive = true;
    TimerObservable.create(0, 10000)
      .pipe(
        takeWhile(() => this.alive)
      )
      .subscribe(() => {
        this.myservice.checkdata().subscribe( result => { this.statustext = result } );
      });
  }

  ngOnDestroy(){
    this.alive = false;
  }
}
Nikson
  • 900
  • 2
  • 21
  • 51
0

I am referring to angular 8:

Please note the difference between timer and interval.

You would use the timer if you want to delay a single function call but you want to use an invertal if you want to fire multiple function calls in sequence with a delay between: http://tutorials.jenkov.com/angularjs/timeout-interval.html

I found the following code snipped in this blog post: http://tutorials.jenkov.com/angularjs/timeout-interval.html

ngOnInit() {
    interval(5000)
      .pipe(
        startWith(0),
        switchMap(() => this.apiService.getTweets())
      )
      .subscribe(res => this.statuses = res.statuses})
    ;
  }
Bolic
  • 705
  • 2
  • 12
  • 30
-2

You can use the setInterval which is quite simple

setInterval(console.log('hi'), 10000);

This runs for every 10 secs

Gvs Akhil
  • 2,165
  • 2
  • 16
  • 33