so I am attempting to poll my server. I am trying to poll my server every 5 seconds. And the poll times out after one minute. I have a few console logs in the method for debugging but the only console.log that fires even after waiting 5 seconds is 'validate stream start'
I followed this tutorial without creating a separate service as I just need it for this one page in my application.
I’m willing to bet its a simple error or a misunderstanding in how these rxjs operators work.
What am I doing wrong?
startastream(){ this.startastreamboolan = true; let count = 12; this.http.get(environment.shochat_content_creator_set_valid_stream_start) .subscribe((req: any)=>{ console.log('validate stream start'); timer(5000).pipe( switchMap(() =>{ console.log('timer start'); if(count > 0){ return this.http.get(environment.check_if_stream_is_active_on_mux) .subscribe( (req: any)=>{ this.streamready = true; return 0; }, error => { count = count -1; console.log(count); }); } })); }); }
Advertisement
Answer
timer
Creates an Observable that starts emitting after an dueTime
and emits ever increasing numbers after each period
of time thereafter.
timer(dueTime: number | Date = 0, periodOrScheduler?: number | SchedulerLike, scheduler?: SchedulerLike): Observable<number>
Its like
interval
, but you can specify when should the emissions start.
In your code, you are forgetting the second parameter of the timer
operator, which means it will just wait for 5s
and then emit only once. In addition, you are not subscribing to the timer
, that’s why it’s not going any further. If you want to poll your server every 5s
, you need to use :
timer(0, 5000)
Here, the timer won’t wait and will directly start emitting values every 5s
.
Next, I see that you’re using a switchMap
to create an inner stream, that’s great. But If your server takes more than 5s
to process your request, you might want to use mergeMap
instead as it doesn’t cancel the previous ongoing inner streams, it’s up to you.
The error here is that the switchMap
(or the mergeMap
) takes a callback function which must return an Observable
, the operator will then subscribe to it by itself. Here, you are returning a Subscription
instead.
Here is what you could do :
const start$ = this.http.get(startUrl).pipe( tap(() => console.log('Stream start')) ); const poll$ = this.http.get(pollUrl).pipe( tap(() => (this.streamReady = true)), catchError(error => { console.log(error); return EMPTY; }) ); start$.pipe( switchMap(() => timer(0, 5000).pipe( tap(() => console.log('Polling every 5s')), mergeMap(() => poll$) )) ).subscribe();
I’ve created two Observables
here. start$
, which is responsible for starting the stream, and poll$
, which is responsible for polling your server. The idea here is to start the stream, then switch to the timer
inner stream which will emit every 5s
, and then switch again to another inner stream that will poll the server.
I didn’t include the count
in my example, so the stream will run forever with this code. You should take a look at the takeUntil
operator for that purpose.
Hope it helped, feel free to ask questions !