簡體   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