我对async
-pipe 与Observable
在OnInit
. 必须是关于OnInit
发生的时间点以及模板被渲染并因此Observable
被订阅的时间点的时间问题。
考虑这个组件:
export class AppComponent implements OnInit {
subjectA$: Subject<{name:string}>;
subjectB$: Subject<{name:string}>;
constructor(
protected http: HttpClient
) {
}
ngOnInit() {
this.subjectA$ = new Subject<{name: string}>();
this.subjectA$.next({name: "A"});
this.subjectB$ = new Subject<{name: string}>();
setTimeout(() => {
this.subjectB$.next({name: "B"});
}, 0);
}
}
和模板:
<p *ngIf='subjectA$ | async as subjectA; else: nosubjectA'>
subjectA: {{subjectA.name}}
</p>
<ng-template #nosubjectA>
<p>no subjectA</p>
</ng-template>
<p *ngIf='subjectB$ | async as subjectB; else: nosubjectB'>
subjectB: {{subjectB.name}}
</p>
<ng-template #nosubjectB>
<p>no subjectB</p>
</ng-template>
这导致
no subjectA
subjectB: B
这意味着:即使在subjectA$
中获得了值onInit
,视图也不会更新。如果我在 a 中创建第一个值,setTimeout
如您所见subjectB$
,它可以工作并且我看到了值。虽然这是一个解决方案,但我想知道为什么会发生这种情况,是否有更好的解决方案?
我已经找到的一个解决方案是使用BehaviorSubject
提供第一个值作为初始值:
this.subjectC$ = new BehaviorSubject<{name: string}>({name: "C"});
与subjectC的类似模板导致subjectC: C
。
我真正的 observable 根本不是Subject
,而是combineLatest
不同东西的 -call 的结果,其中只有一个是(不幸的是,因为它使用来自@Input()
-annotation 的值) a Subject
,并像示例next
中一样手动推送OnInit
. 其余的来自http
等人。很可能我可以将组合结果包装在 a 中,BehaviourSubject
但它对我来说看起来既丑陋又危险,所以它比这种setTimeout
方法更糟糕。但我敢打赌,有人可以帮助我并找到一个真正有用的解决方案。另外,我宁愿避免BehaviorSubject
使用getValue
.