I have a list of servers urls and making sequential http requests to them in a loop. When the success response arrives from the current request I want to break the loop and not to call all other servers. Could someone advice me how this could be handled in Angular/RxJS? Something like:
getClientData() {
for(let server of this.httpsServersList) {
var myObservable = this.queryData(server)
.pipe(
map((response: any) => {
const data = (response || '').trim();
if(data && this.dataIsCorrect(data)) {
return data; // **here I want to break from the loop!**
}
})
);
return myObservable;
}
}
private queryData(url: string) {
return this.http.get(url, { responseType: 'text' });
}
IMO it's better to avoid using a for
loop for subscribing to multiple observables. It might lead to multiple open subscriptions. Common function used for this case is RxJS forkJoin
.
But given your specific condition, I'd suggest using
from
function with concatMap
operator to iterate each observable in orderfilter
operator to ignore empty or undefined and invalid data.take
operator with count
argument set to 1 to close the observable as soon a valid data is emitted (thanks @Akxe in comments).import { from } from 'rxjs';
import { concatMap, filter, map, takeWhile } from 'rxjs/operators';
getClientData(): Observable<any> {
return from(this.httpsServersList).pipe(
concatMap((server: string) => this.queryData(server)),
map((response: any) => (response || '').trim()),
filter((data: string) => !!data && this.dataIsCorrect(data)), // <-- ignore empty or undefined and invalid data
take(1)
);
}
Note: Try to tweak the condition inside the filter
operator to match your requirement.
Edit 1: add inclusive
argument in takeWhile
opeartor
Edit 2: add additional condition in the filter
operator
Edit 3: replace takeWhile
with take
operator (thanks @Akxe in comments)