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