Angular2递归http调用

Angular2递归http调用,angular,recursion,iframe,observable,Angular,Recursion,Iframe,Observable,我在angular中有一个http服务,它返回一个txt/html,我解析响应以查找任何iframe标记,对于每个iframe,我调用相同的服务以获取内部html,它本身也可以有iframe标记等等。 此递归调用将一直执行,直到没有更多的iframe可获取为止。 我想做的是每次处理和更新响应(覆盖iframe的src) //服务 getHtmlFile(文件:字符串){ 常量httpOptions={ headers:new-HttpHeaders('X-request-With':'XMLHt

我在angular中有一个http服务,它返回一个txt/html,我解析响应以查找任何iframe标记,对于每个iframe,我调用相同的服务以获取内部html,它本身也可以有iframe标记等等。 此递归调用将一直执行,直到没有更多的iframe可获取为止。 我想做的是每次处理和更新响应(覆盖iframe的src)

//服务
getHtmlFile(文件:字符串){
常量httpOptions={
headers:new-HttpHeaders('X-request-With':'XMLHttpRequest'}),
//将“响应”视为“响应”,
responseType:“文本”作为“文本”
};
返回this.http.get(url,httpOptions)//设置标题
}
//不起作用
getHtml(文件:字符串){
此.httpService.getHtmlFile(文件)
.订阅(res=>{
const iframes=getIframes(res);//从res获取iframes列表。
//循环遍历列表并递归地获取html文件
for(设i=0;i
我可以对每个请求都这样做,但是我不知道如何在递归调用中累积更改,以便父html res可以从其子级获得更改。订阅者只会得到应用了所有更改的最终结果。不确定这如何与服务的可观察响应一起工作

不确定这是否清楚,但简言之,这是一个树状结构,其中每个节点值(来自可观察值)都应该在其父值(也来自可观察值)中注入/替换

这是角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
//file1.html
//file2.html
//file1_1.html
输出应该是顶级index.html,iframe src作为blob,如下所示。 这里的关键是,file1/file2还应该将其iframes src设置为blob,然后将其在索引帧中设置为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();
      });
  });
}
getHtml=(文件:字符串):可观察{
返回新的可观察对象(观察者=>{
此.httpService.getHtmlFile(文件)
.订阅(res=>{
常数iframes=getIframes(res);
for(设i=0;i{
res=res.replace(iframes[inex],newRes);
});
}
观察员:下一个(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;
    });
}
//服务
getHtmlFile(文件:字符串){
常量httpOptions={
标题:新的HttpHeaders(
{
“X-request-With':“XMLHttpRequest”,
}),
//将“响应”视为“响应”,
responseType:“文本”作为“文本”
};
//设置标题
返回此.http.get(url,httpOptions).pipe(
concatMap((res)=>{
//从res获取iframe列表。
常数iframes=getIframes(res);
//循环遍历列表并递归地获取html文件
for(设i=0;i{
this.variableIncomonent=res;
});
}
通过这种方式,您可以将循环和递归调用隔离到第一个函数中,并使其成为私有的。在subscribe执行之前,无论何时调用getHtml,concatMap块都会执行其操作并返回subscribe的值

无论如何,我并不完全理解您想要实现的目标,但我认为在这种可观察的模式中递归调用有问题

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