我有一个BehaviorSubject,可观察性地将其消耗掉:
testForStack$: Observable<boolean>;
ngOnInit(){
const bs = new BehaviorSubject(true);
this.testForStack$ = bs
.asObservable()
.do(t => console.log('subscribed'))
.share();
}
此可观察对象通过模板中的三个异步管道进行管道传输:
Sub1: {{testForStack$ | async}}<br>
Sub2: {{testForStack$ | async}}<br>
Sub3: {{testForStack$ | async}}
问题是只有第一个(Sub1)的值为true
Sub1: true
Sub2:
Sub3:
如果我删除了.share(),则所有三个值都将获得true值,但这会导致多个订阅问题。
是否有任何关于为什么使用BehaviorSubject导致此行为的想法?它被用作观察对象,因此我认为上面的代码可以正常工作。
这也与此答案类似:
答案 0 :(得分:4)
这是正确的行为。 share()
运算符仅对其父级保留一个订阅,而BehaviorSubject
仅在订阅时发出其值。
这意味着,当您使用第一个{{testForStack$ | async}}
时,它会在链的末尾订阅share()
,后者会订阅其父项,从而导致订阅源BehaviorSubject
发出立即值。
但是,第二个和所有连续的{{testForStack$ | async}}
订阅了share()
,而该shareReplay(1)
已经订阅了其父项,并且不再进行订阅,因此没有任何将源值推送给这些观察者的功能。 / p>
一个简单的解决方案是使用publishReplay(1).refCount()
(取决于您的RxJS版本),由于这些问题(或它的可等效的问题),您可能应该使用tf.top_k
:
答案 1 :(得分:1)
不要使用共享运算符。而是这样做:
<ng-container *ngIf="testForStack$ | async as testForStack">
Sub1: {{ testForStack }}
Sub2: {{ testForStack }}
Sub3: {{ testForStack }}
</ng-container>
还有许多其他方法,例如,如果您不喜欢使用* ngIf,则可以对使用ngTemplateOutlet
的模板使用相同的方法。这种方法允许您以相同的方式创建别名变量:
<ng-template let-testForStack [ngTemplateOutletContext]="{ $implicit: testForStack$ | async }" [ngTemplateOutlet]="selfie" #selfie>
Sub1: {{ testForStack }}
Sub2: {{ testForStack }}
Sub3: {{ testForStack }}
</ng-template>
此ng-template
代码是自引用的(有效),未经完全测试,但“应”起作用,并且避免使用* ngIf
在此处了解更多信息:https://nitayneeman.com/posts/using-single-subscription-for-multiple-async-pipes-in-angular/