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)
);