Reputation: 23
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;
}
});
}
});
}
Upvotes: 1
Views: 1218
Reputation: 14129
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.
Upvotes: 0
Reputation: 57981
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
Upvotes: 1