I am looking to retrieve documents for each city.
I have a first http GET retrieving cities by parsing the page and then I need to make an other request for each city to retrieve associated documents.
What I have done
this.httpService.callUrl(ifrUrl).subscribe((html: string) => {
const root = parse(html);
const nodes = root.querySelectorAll(IFR_AIRPORTS_SELECTOR);
const airports = [];
for (const node of nodes) { // Loop for each city
if (node.childNodes.length === 2) {
const linkElement = node.childNodes[1];
// @ts-ignore
const link = linkElement.attributes.href;
const airportUrl = this.urlService.getIfrUrlWithEnd(link);
const airportName = linkElement.innerText.trim().replace('\n', ' ');
// @ts-ignore
const icaoSplit = linkElement.attributes.id.toString().split('.');
const icao = icaoSplit[icaoSplit.length - 1];
// Retrieve documents associated to the actual airport
// with an other http request
this.getIfrChartsForUrl(airportUrl).subscribe((charts) => {
const airport = new IfrAirport();
airport.icao = icao;
airport.name = airportName;
airport.url = airportUrl;
airport.charts = charts;
});
}
}
console.log('Airports');
console.log(airports);
I am not really familiar with asynchrone functions. Here I try afterward to display the airport but the log is display directly after running the script with empty airport array...
The array build airports
should be returned.
What am I missing?
T H A N K S
Instead of nested subscriptions and subscriptions in a loop you could use RxJS higher order mapping operator like switchMap
to map an observable and forkJoin
function to combine multiple observables.
Try the following
this.httpService.callUrl(ifrUrl).pipe(
switchMap((html: string) => {
const root = parse(html);
const nodes = root.querySelectorAll(IFR_AIRPORTS_SELECTOR);
const requests = [];
for (const node of nodes) { // Loop for each city
if (node.childNodes.length === 2) {
const linkElement = node.childNodes[1];
// @ts-ignore
const link = linkElement.attributes.href;
const airportUrl = this.urlService.getIfrUrlWithEnd(link);
const airportName = linkElement.innerText.trim().replace('\n', ' ');
// @ts-ignore
const icaoSplit = linkElement.attributes.id.toString().split('.');
const icao = icaoSplit[icaoSplit.length - 1];
requests.push(
this.getIfrChartsForUrl(airportUrl).pipe(
map(charts => {
const airport = new IfrAirport();
airport.icao = icao;
airport.name = airportName;
airport.url = airportUrl;
airport.charts = charts;
return airport;
})
)
);
}
}
return forkJoin(requests);
})
).subscribe(
airports => console.log(airports),
err => console.log(err)
);