How to chain these RxJs obersables

14 views
Skip to first unread message

Reza Razavipour

unread,
Oct 1, 2018, 2:02:21 PM10/1/18
to Angular and AngularJS discussion
Using Angular CLI 6 for a Single Page Application

What I need to do is the following
make an HTTP post request. I will get an OK back. The results or the side effect will take sometime before is ready for processing.
I will have to poll for results readiness, lets say once a second.

To poll for the results, I need to make an HTTP get call and check the results. If results are complete, I am done.
Otherwise I will have to continue to poll..

What I have done, I have two obserables, one for the HTTP post and one for HTTP get call. 
I use a setTimeout for the polling. This organization for the code, when I hit the setTimeout, I go to never never land I have to kill the application...

Any hints on this problem?

Reza Razavipour

unread,
Oct 1, 2018, 4:33:42 PM10/1/18
to Angular and AngularJS discussion
So with some help, this is what I have so far:

 private initiateAnalysis() {
    this.initiateRequest$().pipe( // sends the first request to start the analysis
      switchMap(() => interval(1000)), // when the response comes back, start emitting an event every second from this observable
      mergeMap(() => this.checkForResponse$()), // each second, send the GET request and emit the results. Merge all the results into the resulting observable
      filter(results => this.isAnalysisComplete(results)), // filter out the results if they are not the final, correct results
      first() // only take the first complete results, to avoid continuing sending GET requests
    ).subscribe(results => this.showResults(results));
  }

  private initiateRequest$(): Observable<void> {
    const params = {
    };
    return this.problemsService.postRequest('postURL', {}, params)
  }

  private checkForResponse$(): Observable<Results>{
    const params = {
    };

    return this.problemsService.getResults('someURL', params);
  }

  private showResults(results: Results) {
    console.log('results', results);
  }
Except this has one problem. The above code stops processing with the first result from the get.
Not my use case. I need to get a response from the http get call, check the result for some condition, only if the condition 
is met, I stop and show the results.
How can I pull that off?

Sander Elias

unread,
Oct 1, 2018, 11:50:13 PM10/1/18
to Angular and AngularJS discussion
Hi Rezza,

Will be something like:

import { interval, of } from 'rxjs';
import { startWith, switchMap, take, takeWhile, tap } from 'rxjs/operators';

const post$ = of({ ok: true }); // fake http Post.
const log = console.log.bind(console);
// function that returns a fake http get
const isReady = () => of(Math.random() < 0.5).pipe(startWith(false));

post$
.pipe(
switchMap(r => (r.ok ? interval(500) : of(-1))),
switchMap(r => (r < 0 ? of(false) : isReady())),
tap(log),
takeWhile(r => !r), // am I done?
take(10) // protect me from mistakes.
)
.subscribe();


Or did I miss something in what you needed?

Reza Razavipour

unread,
Oct 2, 2018, 1:13:45 PM10/2/18
to ang...@googlegroups.com
this is spot on!

thank you

Regards,
Reza


--
You received this message because you are subscribed to a topic in the Google Groups "Angular and AngularJS discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/jeBO6DeC2VA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at https://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages