I'm using an IntervalObservable
to make continuous calls to the server side of my application. I can subscribe and unsubscribe to to the Oberservable and everything works fine with one exception:
The first call to the server is delayed, but I want it to be instant. The behaviour of the IntervalObservable
is in principle correct, but does not match 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 afterwards with the defined delay?
Two things,
Observable.interval(3000)
instead of IntervalObservable.create
You can use timer
to do it with a single operator instead:
return Observable.timer(0, 1000)
.flatMapTo(this.http.get(this.apiURL))
.map(this.extractData)
.catch(this.handleError);
You can use startWith.
Following example pushes an event on 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);
}
I'd use concat
and concatMap
for this:
See live 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 triggered with Observable.of(null)
which goes through the operator chain and triggers httpRequest
. Then it's all up to the Observable.interval
operator.
For #RxJS Version 5+ :
You can use rxjs interval operator and implement polling. The following implemention will execute the this.statusService.getStatus()
line in every 1000 ms interval :
getList() {
return Observable.interval(1000).startWith(1)
.mergeMapTo(this.http.get(this.apiURL))
.catch(this.handleError);
}
With startWith(1)
added, now, it will be immediately executed without any delay and after that it will be executed every 1 sec interval.
I think this is what you want.
Or Another approach: you can use 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 operator will instantly execute and after that it will execute in every 1000 ms.
Also don't forget to import :
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/mergeMapTo';
import 'rxjs/add/observable/timer';
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With