Angular observable behavior odd when shared

房东的猫 提交于 2019-12-11 08:12:54

问题


I have an observable that when I use the rxjs 'share' operator behaves strangely in the Angular template. Here's how I setup my two observables (in a service):

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;
  })
);

I then add the familyMember observable to my component as a property

this.familyMembers = this.familyService.familyMembers

My markup looks something like this:

 <tbody *ngIf="(familyMembers | async) != null">
        <pre> {{(familyMembers | async) | json}}</pre>

Now the strange thing is when familyMembers is populated (an array of two), the <pre> will render with null inside even after i've checked for null with the *ngIf.

I also have a list that does not render anything as follows:

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

I know that the last thing familyMembers observable emitted was the correct two family members, I've checked this with map and console.log. The Angular template seems to be seeing this as null.. but also not?

Everything works if I remove the share() from the family observable but the tap() runs twice which is not desirable.

EDIT:

Using shareReplay() instead of share() fixed my problem. share() will not re-emit values when all subscriptions unsubscribe.


回答1:


You should use the shared() operator since you are subscribe twice, that's why you got the duplicate.
You should change your html code accordingly :

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

In the first *ngIf you check for the existence of the values, so there is no need to use async pipe again in the other row since it won't be called if its not passed the first one.
Plus, when you calling 'as familyProps' and using it in the next line, you are sure that this local object will be available when this line executes. It might work without the 'as', but from your comment, I just add it to make sure.

--EDIT
Each async pipe that you call will subscribe too, now what happen is that the first line with *ngIf waiting for the values, and the second line located inside this wrapper, so it won't call until the first line executes.
Now, when the first line pass, the second line will try to subscribe with the async pipe but its already completes, because of the first line subscription and the shared() operator.
You can try this, and it should work as well:

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


来源:https://stackoverflow.com/questions/51327651/angular-observable-behavior-odd-when-shared

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!