繁体   English   中英

Angular2递归http调用

[英]Angular2 recursive http calls

我有一个Angular的http服务,它返回一个txt / html,我解析响应以查找任何iframe标签,对于每个iframe,我都调用相同的服务来获取内部html,该html内部也可以具有iframe标签,依此类推。 进行此递归调用,直到没有更多iframe可供提取为止。 我想做的是每次处理和更新响应(覆盖iframe的src)。

//service
getHtmlFile(file: string) {
  const httpOptions = {
    headers: new HttpHeaders('X-Requested-With': 'XMLHttpRequest'}),
    //observe: 'response' as 'response',
    responseType: 'text' as 'text'
  };

  return this.http.get(url, httpOptions); //set headers
}

//Not working
getHtml(file: string) {
this.httpService.getHtmlFile(file)
  .subscribe(res => {
    const iframes = getIframes(res); //get list of iframes from res.
    //loop through the list and recursively get html files
    for (let i = 0; i < iframes.length; i++) {
       const src = extractSrc(iframes[i]);//extract the src attribute
       this.getHtml(src);//recursive call
       res = res.replace(iframes[i], newvalue); //want to update res here?
    }
    return res;
  });
}

我可以为每个请求执行此操作,但无法弄清楚如何在递归调用中累积更改,以使父html res从其子级获得更改。 订户只会得到应用了所有更改的最终结果。 不确定该服务如何与可观察到的响应一起工作?

不知道这是否清楚,但简而言之,它是树状结构,其中每个节点值(来自Observable)都应注入/替换为其父值(也来自Observable)!

这是Angular 5。

遇到了角度扩展选项,但不确定如何使用它维护树结构。 这是一个类似的问题链接

//编辑

抱歉,如果我不清楚要实现什么。 这是输入文件和所需输出结果的示例。 希望这现在有意义。

//index.html
<html>
<body>
  <!-- iframes -->
  <iframe src="file1.html"></iframe>
  <iframe src="file2.html"></iframe>
</body>
</html>

//file1.html
<html>
<body>
  <!-- iframes -->
  <iframe src="file1_1.html"></iframe>
</body>
</html>

//file2.html
<html>
<body>
  <!-- body with no iframes -->
</body>
</html>

//file1_1.html
<html>
<body>
  <!-- body with no iframes -->
</body>
</html>

输出应为顶级index.html,其中iframe src为blob,如下所示。 这里的关键是file1 / file2在将其iframe src设置为blob之前,还应该将其iframe src设置为blob,依此类推。

<html>
<body>
  <!-- iframes -->
  <iframe src="blob(file1)"></iframe>
  <iframe src="blob(file2)"></iframe>
</body>
</html>

这不会解决您的全部问题,但是部分问题是您需要订阅服务。 否则,该功能将在您完成处理之前终止。

getHtml = (file: string): Observable<any>{
  return new Observable<any>(observer => {
    this.httpService.getHtmlFile(file)
      .subscribe(res => {

        const iframes = getIframes(res);

        for (let i = 0; i < iframes.length; i++) {
          const index = i; // not sure if you need this, but you might lose scope in your loop
          const src = extractSrc(iframes[i]);
          this.getHtml(src).subscribe(newRes => {
            res = res.replace(iframes[inex], newRes);
          });
        }

        observer.next(res);
        observer.complete();
      });
  });
}

使用rxjs Observable 编辑此解决方案

我认为这完全符合您的编码方式。 在我看来,这里的关键是您在返回价值,但是没人期望它。 我要做的是将最终值存储到变量中,而不是返回它。

为了将行为隔离到服务中,我还使用了concatMap。 现在,我认为这是您想要的:

//service
getHtmlFile(file: string) {
  const httpOptions = {
    headers: new HttpHeaders(
    {
      'X-Requested-With': 'XMLHttpRequest',
    }),
    //observe: 'response' as 'response',
    responseType: 'text' as 'text'
  };

  //set headers
  return this.http.get(url, httpOptions).pipe(
    concatMap( (res) => {
        //get list of iframes from res.
        const iframes = getIframes(res);

        //loop through the list and recursively get html files
        for (let i = 0; i < iframes.length; i++) {
           //extract the src attribute
           const src = extractSrc(iframes[i]);

           //recursive call
           this.getHtml(src);

           //want to update res here?
           res = res.replace(iframes[i], newvalue);
        }

        return res;
   }));
}

//not working
getHtml(file: string) {
  this.httpService.getHtmlFile(file)
    .subscribe( res => {
       this.variableInComponent = res;
    });
}

这样,您可以将循环和递归调用隔离到第一个函数中,并将其设为私有。 每次调用getHtml时,在订阅执行之前,concatMap块都会执行操作并返回要订阅的值。

无论如何,我都不了解您想要实现的目标,但是我认为这种可观察的模式中的递归调用存在一些问题...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM