Angular:如何在订阅模板之前管道Observable



免责声明:这与此问题密切相关。

目前我有两个组件,ParentChildParent将一个Observable传递给Child,后者在模板中订阅该Observable以避免生命周期/内存泄漏问题。但我必须在Child组件中pipe的Observable来设置一些东西。

parent.ts:

public $obs = Observable<any>;
....
loadData() {
this.obs$ = this.myService.getData();
}

parent.html:

<child [data$]="obs$"></child>

child.ts:

@Input() data$ : Observable<any>;
ngOnChanges(changes) {
if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}
}

child.html

<div *ngIf="data$ | async as data;">
{{ data || json }}
</div>

数据存在于模板中,控制台日志显示已检测到更改,但";tap-worked";从未显示,这让我怀疑我打给pipe的电话可能来晚了。是否有任何方法可以在模板";呼叫";订阅

这个想法是有许多类似于child的组件,所有组件都在数据对象上做不同的事情。我考虑订阅Parent中的服务,并将json值直接传递给所有子级,但这需要我在所有子级中编写一个*ngIf

我建议您不要直接订阅data$。相反,创建另一个你可以阅读的Observable。

@Input() data$: Observable<any>;
customData$: Observable<any>;
ngOnChanges(changes) {
if(changes.data$) {
console.log("changes detected");
this.customData$ = this.data$.pipe(tap(data => console.log("tap worked")));
}
}
<div *ngIf="customData$ | async as data;">
{{ data || json }}
</div>

观察者天生懒惰。在您订阅它们之前,它们不会被执行。要查看";tap-worked";你需要订阅它。

this.data$.pipe(tap(data => console.log("tap worked"))).subscribe();

默认情况下,async为您订阅和取消订阅observable,还请注意,observable中的每个订阅程序都会获得一个新的执行上下文,并且这种行为可以被覆盖。

为了在订阅延迟的情况下缓存结果,您可以在服务中使用BehaviourSubjectReplaySubject

我认为问题出在ngOnChanges中。你有条件

if(changes.data$) {
console.log("changes detected");
this.data$.pipe(tap(data => console.log("tap worked")));
}

这将检查数据$的引用是否会更改,但不检查数据$是否发出您实际想要的新值。因此,您的tap不会执行。

相反,你可以

public data$: Observable<any>;
@Input() set data(data$: Observable<any>) {
this.data$ = data$.pipe(tap(x => console.log("tap worked")));
}

最新更新