Retry the request (Angular2 - http.get) a few seconds after completion

I played with angular2 and got stuck after a while.

Using http.get works fine for a single request, but I want to poll live data every 4 seconds, after http.get and reading a lot of http.get with http.get I ended up:

 Observable.timer(0,4000) .flatMap( () => this._http.get(this._url) .share() .map(this.extractData) .catch(this.handleError) ) .share(); 

Is there an easy way to start the interval (4 seconds) after http.get -observable sends the result of the request? (Or will I go to observable hell?)

Dates I want:

 Time(s): 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 Action: Request - - Response - - - - - - - - - - - - - - - - - - - -Request-... Wait: | wait for 4 seconds -------------------------> | 
+9
javascript angular observable rxjs reactivex
source share
4 answers

Upgrade to RxJS 6

 import { timer } from 'rxjs'; import { concatMap, map, expand, catchError } from 'rxjs/operators'; pollData$ = this._http.get(this._url) .pipe( map(this.extractData), catchError(this.handleError) ); pollData$.pipe( expand(_ => timer(4000).pipe(concatMap(_ => pollData$))) ).subscribe(); 

I am using RxJS 5, and I'm not sure if the equivalent operators are RxJS 4. Anyway, here is my RxJS 5 solution, hope it helps:

 var pollData = this._http.get(this._url) .map(this.extractData) .catch(this.handleError); pollData.expand( () => Observable.timer(4000).concatMap(() => pollData) ).subscribe(); 

The extension operator sends data and recursively launches a new observable with each radiation

+10
source

I managed to do this myself, with the only drawback being that http.get cannot be repeated more easily.

 pollData(): Observable<any> { //Creating a subject var pollSubject = new Subject<any>(); //Define the Function which subscribes our pollSubject to a new http.get observable (see _pollLiveData() below) var subscribeToNewRequestObservable = () => { this._pollLiveData() .subscribe( (res) => { pollSubject.next(res) } ); }; //Subscribe our "subscription-function" to custom subject (observable) with 4000ms of delay added pollSubject.delay(4000).subscribe(subscribeToNewRequestObservable); //Call the "subscription-function" to execute the first request subscribeToNewRequestObservable(); //Return observable of our subject return pollSubject.asObservable(); } private _pollLiveData() { var url = 'http://localhost:4711/poll/'; return this._http.get(url) .map( (res) => { return res.json(); } ); }; 

This is why you cannot use a more direct subscription:

 var subscribeToNewRequestObservable = () => { this._pollLiveData() .subscribe(pollSubject); }; 

Completion http.get -observable will also terminate your object and prevent it from emitting additional elements.


This is still coldly observable, so if you are not subscribed to it, requests will not be made.

 this._pollService.pollData().subscribe( (res) => { this.count = res.count; } ); 
+2
source

Minor refinement of the response from Can Nguyen if you want the polling delay to depend on the previous request completion status.

 var pollData = () => request() // make request .do(handler, errorHandler) // handle response data or error .ignoreElements() // ignore request progress notifications .materialize(); // wrap error/complete notif-ns into Notification pollData() // get our Observable<Notification>... .expand( // ...and recursively map... (n) => Rx.Observable // ...each Notification object... .timer(n.error ? 1000 : 5000) // ...(with delay depending on previous completion status)... .concatMap(() => pollData())) // ...to new Observable<Notification> .subscribe(); 

Plunk .

Or alternatively:

 var pollData = () => request() // make request .last() // take last progress value .catch(() => Rx.Observable.of(null)); // replace error with null-value pollData() .expand( (data) => Rx.Observable .timer(data ? 5000 : 1000) // delay depends on a value .concatMap(() => pollData())) .subscribe((d) => {console.log(d);}); // can subscribe to the value stream at the end 

Plunk .

+1
source

You can try to use the interval if it is more convenient. The subscribe call gives you a Subscription , which allows you to cancel the survey after a while.

 let observer = Observable.interval(1000 * 4); let subscription = observer.subsscribe(x => { this._http.get(this._url) .share() .map(this.extractData) .catch(this.handleError) }); .... // if you don't require to poll anymore.. subscription.unsubscribe(); 
-one
source

All Articles