Start first call IntervalObservable instant

I use IntervalObservable for continuous server-side calls of my application. I can subscribe and unsubscribe to Oberservable, and everything works fine with one exception:

The first server call is delayed, but I want it to be instant. The behavior of IntervalObservable in principle correct, but does not meet my requirements.

 @Injectable() export class LoggerService { constructor(private http: Http) { } private apiURL = 'assets/file.json'; getList() { return IntervalObservable.create(1000).flatMap(() => this.http.get(this.apiURL)) .map(this.extractData) .catch(this.handleError); } private extractData(res: Response) { var fooot = new Foo(); fooot.fillFromJSON(JSON.stringify(res.json())); return fooot; } private handleError(error: any) { let errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error'; console.error(errMsg); return IntervalObservable.throw(errMsg); } } 

So, how can I call the server instant on the first call, and then with a certain delay?

+5
source share
4 answers

Two things,

  • You can use factory methods instead of derived types, i.e. Observable.interval(3000) instead of IntervalObservable.create
  • You can use timer for this with a single statement:

     return Observable.timer(0, 1000) .flatMapTo(this.http.get(this.apiURL)) .map(this.extractData) .catch(this.handleError); 
+7
source

You can use startWith .

The following example pushes the event into the stream when it is created:

  getList() { return IntervalObservable.create(1000) .startWith(1) // needs a value, but won't be used .flatMap(() => this.http.get(this.apiURL)) .map(this.extractData) .catch(this.handleError); } 
+4
source

I would use concat and concatMap for this:

See demo: http://plnkr.co/edit/4kdJRD7HZqrbce7MFPW7

 import {Observable} from 'rxjs'; let httpRequest = () => Observable.of('response'); Observable.of(null) .concat(Observable.interval(3000)) .concatMap(httpRequest) .subscribe((response) => console.log(response)); 

The first request is launched using Observable.of(null) , which goes through a chain of statements and fires httpRequest . Then all this is up to the Observable.interval operator.

+2
source

For #RxJS version 5+:

You can use the rxjs interval operator and do the polling. The following execution will execute the line this.statusService.getStatus() for each 1000 ms interval:

  getList() { return Observable.interval(1000).startWith(1) .mergeMapTo(this.http.get(this.apiURL)) .catch(this.handleError); } 

When adding startWith(1) it will now be executed immediately without any delay, after which it will be executed every 1 second. I think this is what you want.

Or another approach: you can use the timer operator and do the following:

 getList() { return Observable.timer(0, 1000) .mergeMapTo(this.http.get(this.apiURL)) .catch(this.handleError); } 

In this approach, the timer statement will execute instantly, and after that it will be executed every 1000 ms.

Also do not forget to import:

  import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/startWith'; import 'rxjs/add/operator/mergeMapTo'; import 'rxjs/add/observable/timer'; 
+1
source

Source: https://habr.com/ru/post/1258074/


All Articles