我对我的Observable看到的竞赛案例有疑问。这可能更像是一个一般的可观察/角度问题。从一条路线过渡到另一条路线时,我看到一个cannot read 'property' of undefined error
在控制器上正在销毁,因为我们过渡到一条新路线。在我的控制器中,我有一个像这样的方法:
// this.setting$: Observable<object>;
get name$: Observable<string> {
return this.settings$.pipe(map(settings => settings.name));
}
上面的函数抛出错误。 在相同的组件模板中,我得到了:
<some-component [name]="name$ | async"></some-component>
当我切换到新页面时,this.settings$
选择器将返回undefined,并且我的控制器的代码将引发错误。奇怪的是,发生控制台错误时(通过控制台日志记录ngOnDestroy进行了测试),我的组件已经被破坏。
我找到了两种解决问题的解决方案。解决方案A:
// Parse the name property in the template - which I think looks ugly
<some-component [name]="(settings$ | async).name"></some-component>
或者,解决方案B:
// Pass entire settings object into component and parse out name in some-component controller - yuck
<some-component [settings]="settings$ | async"></some-component>
我不喜欢任何一种解决方案。解决方案A我不喜欢,因为它在模板中看起来很笨拙-但也许我应该处理它。解决方案B我不喜欢,因为它不是一个完美的解决方案。
我不太明白为什么两种解决方案都能解决问题。任何人都可以指出为什么存在此问题吗?特别是考虑到组件已被破坏。感觉像是一个孤立的订阅,但我不知道如何。
编辑:我创建了一个重现该问题的stackblitz。 https://stackblitz.com/edit/ngxs-repro-ndaco6。一共有三种路由:/ home,/ profile,/ settings。 / profile和/ settings取决于URL中的帐户ID。 / home没有。从/ profile到/ home路由时,请注意没有控制台错误。但是,当您从/ settings路由到/ home时,会出现控制台错误。有人可以帮我理解为什么吗?请注意,引发错误时,引发错误的SettingsComponent已被破坏。
答案 0 :(得分:1)
使用
name$ = this.settings$.pipe(map(settings => settings ? settings.name : null));
它会检查设置是否具有值并重复使用相同的可观察对象,而无需在每次访问getter时都重新创建可观察对象。
答案 1 :(得分:0)
account $在销毁组件之前发出不确定的消息,这是在销毁组件之前在路由选择器中发生的情况。
尝试
age$ = this.account$.pipe(
tap(val => {
console.log('Account obs val is', val);
}),
map(account => account.age)
);
https://stackblitz.com/edit/ngxs-repro-ceetsi?file=src/app/components/settings.component.ts
您可以看到在销毁组件之前account $会发出未定义的消息。
只有当您从设置导航到主页时,它才会发生,它是您的路由选择器,导致其未定义发出。