1

I have an Angular code where in i am trying to subscribe to my 1st api and implementing a while loop inside this subscription. Further i need to subscribe to another api inside the while loop. Reason --> I need to subscribe to the inner api multiple times and the while loop should end based on a flag returned by inner api. I tried implementing the below but its not working. Need some help.

CallBanyanToFetchQuotes() {
    const url1 = 'http://ws.integration.banyantechnology.com/services/api/rest/ImportForQuote';

    this.http.post(url1, payload)
      .subscribe(importForQuoteResponse => {
        this.importForQuoteResponse = importForQuoteResponse;
        console.log('LoadID = ' + this.importForQuoteResponse.Load.Loadinfo.LoadID);
        this.loadId = this.importForQuoteResponse.Load.Loadinfo.LoadID;

        while (!this.ratingCompleted) {
          const url2 = 'http://ws.integration.banyantechnology.com/services/api/rest/GetQuotes';

          this.http.post(url2, payload)
            .subscribe(getQuoteResponse => {
              this.getQuoteResponse = getQuoteResponse;
              if (this.getQuoteResponse.RatingCompleted === true) {
                this.ratingCompleted = true;
              }
            });
        }
      });
  }

2 Answers 2

1
this.http.post(url1, payload).pipe(
   switchMap(importForQuoteResponse=>{
      this.importForQuoteResponse = importForQuoteResponse;
      this.loadId = this.importForQuoteResponse.Load.Loadinfo.LoadID;
      return timer(0,1000).pipe(
         switchMap(()=>this.http.post(url2, payload)),
         tap(res=>this.getQuoteResponse=res),
         takeWhile(res=>!res.RatingCompleted,true),
         filter(res=>res.RatingCompleted === true)
      )
   })).subscribe(()=>{
     this.ratingCompleted = true;
   })

a "fool example" in stackblitz

the before code can be explained like: we make the first post, but, we don't want this subscribtion, so we change this subscription to a timer (switchMap). But we don't want the timer, else a second post (another switchMap). Each time timer is executed, is executed the second post and we get the response using tap. We make the call while the response was false (takeWhile) -it's important make the takewhile(...,true), the "true" makes return the last value- and filter the response (filter) so only get the "subscribe" when the response is true.

NOTE: I use timer(0,1000) to make a call each 1000 miliseconds, feel free to change the interval

Sign up to request clarification or add additional context in comments.

1 Comment

Depending on the desired behaviour mergeMap or concatMap could be used instead of the inner switchMap. If timer emits faster than your inner http requests respond with switchMap you're previous request will be cancelled, with mergeMap multiple request will be pending at the same time, with concatMap the next request will only be made after the previous completed.
0

You can use expand to simulate a while loop. expand passes the input through to the destination immediately, maps to an Observable and receives its output as the next input. Map to EMPTY to end this recursion.

// move the urls out of the function if they are static
const url1 = 'http://ws.integration.banyantechnology.com/services/api/rest/ImportForQuote';
const url2 = 'http://ws.integration.banyantechnology.com/services/api/rest/GetQuotes';

callBanyanToFetchQuotes() {
    this.http.post(url1, payload).pipe(
      // process response from url1 http request
      tap(importForQuoteResponse => {
        this.importForQuoteResponse = importForQuoteResponse;
        console.log('LoadID = ' + this.importForQuoteResponse.Load.Loadinfo.LoadID);
        this.loadId = this.importForQuoteResponse.Load.Loadinfo.LoadID;
      }),
      // switch to url2 http request
      switchMap(_ => this.http.post(url2, payload))
      // execute url2 request again if the rating is incomplete or end execution with EMTPY
      expand(quoteResponse => quoteResponse.RatingCompleted ? EMPTY : this.http.post(url2, payload))
      // process responses from url2 requests  
    ).subscribe(quoteResponse => {
      this.getQuoteResponse = quoteResponse;
      if (quoteResponse.RatingCompleted === true) {
        this.ratingCompleted = true;
      }
    });
}

The expand approach guarantees that the next http call will be made directly and only after you received a response from the previous one.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.