Angular 订阅中的订阅循环
Angular subscribe loop in subscribe
我正在寻找检索每个城市的文档。
我有一个通过解析页面检索城市的第一个 http GET,然后我需要为每个城市发出另一个请求以检索相关文档。
我做了什么
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);
我对异步函数不是很熟悉。之后我尝试显示机场,但日志直接显示在 运行 带有空机场数组的脚本之后...
应返回数组构建 airports
。
我错过了什么?
T H A N K S
您可以使用 RxJS 高阶映射运算符,例如 switchMap
来映射一个可观察对象,并使用 forkJoin
函数来组合多个可观察对象,而不是循环中的嵌套订阅和订阅。
尝试以下方法
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)
);
我正在寻找检索每个城市的文档。
我有一个通过解析页面检索城市的第一个 http GET,然后我需要为每个城市发出另一个请求以检索相关文档。
我做了什么
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);
我对异步函数不是很熟悉。之后我尝试显示机场,但日志直接显示在 运行 带有空机场数组的脚本之后...
应返回数组构建 airports
。
我错过了什么?
T H A N K S
您可以使用 RxJS 高阶映射运算符,例如 switchMap
来映射一个可观察对象,并使用 forkJoin
函数来组合多个可观察对象,而不是循环中的嵌套订阅和订阅。
尝试以下方法
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)
);