【问题标题】:Angular observable behavior odd when shared共享时的角度可观察行为奇怪
【发布时间】:2018-07-14 00:17:53
【问题描述】:

我有一个可观察的,当我使用 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 被填充(两个数组)时,&lt;pre&gt; 将在内部呈现null,即使我已经使用*ngIf 检查了null。

我还有一个不呈现任何内容的列表,如下所示:

<ng-template ngFor let-familyMember let-i="index" [ngForOf]="(familyMembers | async)" [ngForTrackBy]="trackByFn">

我知道familyMembers observable 发出的最后一件事是正确的两个家庭成员,我已经用mapconsole.log 进行了检查。 Angular 模板似乎将其视为 null.. 但也不是?

如果我从可观察的家庭中删除 share() 一切正常,但 tap() 运行两次,这是不可取的。

编辑:

使用 shareReplay() 而不是 share() 解决了我的问题。当所有订阅都取消订阅时,share() 不会重新发出值。

【问题讨论】:

  • 尝试 0 | async"> 然后,
     {{familyMembers | json}}
  • 0"> 导致错误:无法读取 null 的属性“长度”
  • 这不是我写的,但再试一次: 然后,
     {{familyProps | json}}
    ,注意我写的内容,不添加你的添加就试试,如果它不起作用,试着找出别的东西
  • 您的第二个建议奏效并呈现了预期的结果 - 我不明白为什么使用“as”会对它产生任何影响。
  • 我添加了答案,如果对你有帮助,请随时标记,祝你好运!

标签: angular rxjs ngrx


【解决方案1】:

您应该使用 shared() 运算符,因为您订阅了两次,这就是您得到重复的原因。
您应该相应地更改您的 html 代码:

 <tbody *ngIf="familyMembers | async as familyProps">
        <pre> {{familyProps | json}}</pre> 

在第一个 *ngIf 中检查值是否存在,因此无需在另一行中再次使用异步管道,因为如果它没有通过第一个,它将不会被调用。
另外,当您调用 'as familyProps' 并在下一行中使用它时,您可以确定当此行执行时该本地对象将可用。没有'as'它可能会工作,但从你的评论中,我只是添加它以确保。

--编辑
您调用的每个异步管道也将订阅,现在发生的是带有 *ngIf 的第一行等待值,第二行位于此包装器内,因此在第一行执行之前它不会调用。
现在,当第一行通过时,第二行将尝试使用异步管道订阅,但由于第一行订阅和 shared() 运算符,它已经完成。
你可以试试这个,它应该也可以:

<tbody *ngIf="familyMembers | async">
  <pre> {{familyMembers | json}} </pre> 

【讨论】:

  • @that_guy ,检查编辑,希望对理解有所帮助。
  • 我明白了,所以一旦家庭 observable 的所有订阅都取消订阅,observable 就完成并且不会再发出任何值?
  • 如果会有更多的值取决于你的决定和项目,但问题是你的第二个异步管道在 observable 完成后被调用。
  • 使用 shareReplay() 解决了我所有的问题 - 感谢您的帮助
猜你喜欢
相关资源
最近更新 更多
热门标签