我可以观察到,当我使用rxjs的“ share”运算符时,在Angular模板中的行为会很奇怪。这是我在服务中设置两个可观察对象的方法:
this.family = this.store.select(getFamily).pipe(
tap(family => {
if (family == null) {
this.loadFamily();
}
}),
filter(family => family != null),
share(),
);
this.familyMembers = this.family.pipe(
map(family => {
return family.familyMembers;
})
);
然后我将可观察到的familyMember作为属性添加到我的组件中
this.familyMembers = this.familyService.familyMembers
我的标记看起来像这样:
<tbody *ngIf="(familyMembers | async) != null">
<pre> {{(familyMembers | async) | json}}</pre>
现在奇怪的是,当填充familyMembers(两个数组)时,即使在我使用<pre>
检查是否为null的情况下,null
仍将使用*ngIf
进行渲染。
我还有一个列表,其中没有任何内容,如下所示:
<ng-template ngFor let-familyMember let-i="index" [ngForOf]="(familyMembers | async)" [ngForTrackBy]="trackByFn">
我知道发出的最后familyMembers
是正确的两个家庭成员,我已经用map
和console.log
进行了检查。 Angular模板似乎将其视为null ..但不是吗?
如果我从可观察的家庭中删除share()
,但tap()
运行两次,则一切正常。
编辑:
使用shareReplay()而不是share()解决了我的问题。当所有订阅退订时,share()不会重新发送值。
答案 0 :(得分:1)
您应该使用shared()运算符,因为您两次订阅,所以才得到重复的。
您应该相应地更改html代码:
<tbody *ngIf="familyMembers | async as familyProps">
<pre> {{familyProps | json}}</pre>
在第一个* ng中,如果您检查值的存在,则无需在另一行中再次使用异步管道,因为如果未通过第一个异步管道,则不会调用它。
另外,当您调用“ as familyProps”并在下一行中使用它时,请确保在执行此行时此本地对象将可用。如果没有'as',它可能会起作用,但是根据您的评论,我只是添加来确保它。
-编辑
您调用的每个异步管道也都将订阅,现在发生的是第一行带有* ngIf等待值,第二行位于此包装器内,因此它将在第一行执行之前不会调用。
现在,当第一行通过时,第二行将尝试使用异步管道进行订阅,但由于第一行订阅和shared()运算符,其已经完成。
您可以尝试一下,它也应该可以工作:
<tbody *ngIf="familyMembers | async">
<pre> {{familyMembers | json}} </pre>