简体   繁体   English

Angular2递归http调用

[英]Angular2 recursive http calls

I have a http service in angular which returns a txt/html, I parse the response to find any iframe tags and for each iframe I call the same service to get the inner html which in itself can also have iframe tags and so on. 我有一个Angular的http服务,它返回一个txt / html,我解析响应以查找任何iframe标签,对于每个iframe,我都调用相同的服务来获取内部html,该html内部也可以具有iframe标签,依此类推。 This recursive call is done until there is no more iframes to fetch. 进行此递归调用,直到没有更多iframe可供提取为止。 What I want to do is to process & update the response each time (overwrite the src of the 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;
  });
}

I can do this for each request but can't figure out how to accumulate the changes in the recursive call so that the parent html res will have the changes from its childs. 我可以为每个请求执行此操作,但无法弄清楚如何在递归调用中累积更改,以使父html res从其子级获得更改。 The subscriber would only get the final result which has all the changes applied. 订户只会得到应用了所有更改的最终结果。 Not sure how this works with observable response from the service? 不确定该服务如何与可观察到的响应一起工作?

Not sure if this is clear, but in short, its a tree like structure where each node value (from Observable) should be injected/replaced in its parent value (also from Observable)! 不知道这是否清楚,但简而言之,它是树状结构,其中每个节点值(来自Observable)都应注入/替换为其父值(也来自Observable)!

This is Angular 5. 这是Angular 5。

Came across angular expand option but not sure how to maintain the tree structure with it. 遇到了角度扩展选项,但不确定如何使用它维护树结构。 This is a similar question link 这是一个类似的问题链接

//Edit //编辑

Sorry if what I'm trying to achieve is not clear. 抱歉,如果我不清楚要实现什么。 Here is example of input files and the desired output result. 这是输入文件和所需输出结果的示例。 Hope this makes sense now. 希望这现在有意义。

//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>

output should be top level index.html with iframe src as blobs, as below. 输出应为顶级index.html,其中iframe src为blob,如下所示。 The key here is that file1/file2 should also have its iframes src set as blob before its set in index frames as blob, and so on. 这里的关键是file1 / file2在将其iframe src设置为blob之前,还应该将其iframe src设置为blob,依此类推。

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

This wont solve your full problem, but part of your problem is that you need to subscribe to your service. 这不会解决您的全部问题,但是部分问题是您需要订阅服务。 Otherwise the function will terminate before you are done processing. 否则,该功能将在您完成处理之前终止。

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

edit this solution utilizes the rxjs Observable 使用rxjs Observable 编辑此解决方案

I think that´s working exactly how you coded. 我认为这完全符合您的编码方式。 The key here is, in my opinion, you´re returning the value, but no one is expecting it. 在我看来,这里的关键是您在返回价值,但是没人期望它。 What I would do is store the final value into a variable instead returning it. 我要做的是将最终值存储到变量中,而不是返回它。

In order to isolate the behaviour into the service, I also use concatMap. 为了将行为隔离到服务中,我还使用了concatMap。 Now, I think this is what you want: 现在,我认为这是您想要的:

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

This way, you can isolate the loop and recursive call into the first function, and make it private. 这样,您可以将循环和递归调用隔离到第一个函数中,并将其设为私有。 Any time you call getHtml, before subscribe execute, the concatMap block will do his thing and return the value to subscribe. 每次调用getHtml时,在订阅执行之前,concatMap块都会执行操作并返回要订阅的值。

In any case, I didn´t understand all you want to achieve, but I think there´s something wrong with the recursive call in this observable pattern... 无论如何,我都不了解您想要实现的目标,但是我认为这种可观察的模式中的递归调用存在一些问题...

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

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