我有一个表,其中有一列需要每个记录的HTTP请求的值,所以我使用了一个方法,返回如下的可观察对象:
getItem(obj): Observable<string> {
return this.http.get('/someServiceurl').pipe(
map(res => {
var x = res.element
return x;
});
}
在表中,行如下所示(其中输入类型为字符串):
<td>
<component [input]="(getItem(obj) | async)">
</component>
</td>
发生的情况是,即使没有将值传递给组件输入,它也会进行无限次HTTP调用,尽管值是从HTTP调用返回的。
那么是什么原因导致的,是否有另一种方法可以在循环中异步调用表中的每个元素的HTTP。
谢谢。
下面是整个表的结构:
<p-table [value]="mainList"
[totalRecords]="Count" [paginator]="true" [showCurrentPageReport]="true"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries" [rows]="5">
<ng-template pTemplate="header">
<tr>
<th>..........</th>
<th>..........</th>
<th>..........</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-obj>
<tr>
<td>{{obj.date}}</td>
<td>{{obj.status}}</td>
<td>
<component [input]="(getItem(obj) | async)">
</component>
</td>
</tr>
</ng-template>
</p-table>
所以是的,这会导致无限的更改检测循环。模板中的函数在每个更改检测周期中运行,这会导致构造一个新的可观察对象,从而导致异步管道运行,然后从异步管道输出导致更改检测周期。冲洗,重复。
管道方法的工作原理是,通过确保仅在其输入(本例中为obj
)发生变化时才构建可观察对象,从而打破循环。如果你需要经常以同样的方式构建同一个可观察对象,这可能是更合适的课程,但如果你只在这里做它,可能会有点沉重。
另一种方法是在表中的项上设置可观察对象。类似于。
// this is just a guess / example. i don't know how your mainList is actually built
this.mainList = this.service.fetchList().map(i => {
i.item$ = this.getItem(i);
return i;
})
then in template:
<component [input]="obj.item$ | async"></component>
这同样确保了列表中每个项的可观察对象只在列表本身被构建时才被构建。
另一种选择是只处理子组件中的下标,但可能出于其他原因不想这样做。
<component [input]="(getItem(obj) | async)"></component>
看起来像是罪魁祸首(让我猜猜,更改检测策略:default?)在每个更改检测周期中,表达式getItem(obj)
被求值,http.get
被调用,请求发出,并且,我猜,这触发了更改,这触发了更改检测,然后我们又来了。
一个可能的解决方案:从
http.get('/someServiceurl').pipe(map(res => res.element))
创建一个管道:
@Pipe({name: 'getItem'})
export class GetItemPipe implements PipeTransform {
constructor(private http: HttpClient) {}
transform(value: string): Observable<SomeInterface> {
return this.http.get(value).pipe(map(res => res.element));
}
}
和模板中的
<component [input]="obj | getItem | async"></component>