订阅中的角度订阅循环

时间:2020-09-24 08:19:23

标签: angular typescript http ionic-framework 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

1 个答案:

答案 0 :(得分:2)

您可以使用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)
);