我在Angular应用程序中遇到一个非常奇怪的错误。我有一个“注销”按钮,当按下该按钮时,调度一些操作以设置存储中的参数,而这些参数不再需要取消定义。我还有一个名为 Storage 的组件,该组件(除其他外)在其NgOnInit()
方法中捕获状态。该方法的结构如下:
this.store.pipe(select(userProfile)).pipe(
switchMap( user => {
if (!currentUser) {
throw new Error('User must be logged in');
}
// ... do something ...
return this.store.pipe(select(userResources));
}
),
switchMap(
response => {
// ... more operations ...
return ...
}
)
).subscribe(
response => {
console.log("GOT RESPONSE");
},
(error: HttpErrorResponse) => {
console.log(error);
console.log("GOT ERROR");
}
);
每次显示此组件并调用此方法时,一切都将正常运行,检索所需的状态并将信息显示给用户。奇怪的是,无论何时我经过此组件(例如,我转到“存储”页面然后再返回到主页),如果在按“注销”按钮后,都将引发错误“用户必须登录”。即使我不在显示该组件的页面上,store.pipe也会再次执行! ngOnInit()
本身不会被重新执行或调用(当我按Logout时,我毕竟不在该组件中,我只是路过),但是那部分代码被执行了,我也不知道为什么。
此外,我提到的那部分代码似乎执行了我通过“存储”页面传递的次数(例如,如果我通过“存储”页面传递了3次,则在收到3次之后出现“ GOT ERROR”消息)
“注销”按钮执行以下操作:
this.authenticationService.logout();
this.router.navigateByUrl(`/`);
this.resourceStore.dispatch(new Logout());
this.store.dispatch(new Logout());
有什么主意吗?这里有我不知道的某种连锁反应吗?
答案 0 :(得分:1)
订阅存在于组件的生存期之外。常见的内存泄漏是在通过ngOnDestroy生命周期挂钩销毁组件时忘记取消订阅。
选择器也将在相关状态改变时触发,从而重复执行
可以找到更全面的讨论here
您可以通过添加以下内容来修复代码:
private destroyed$ = new Subject<void>()
ngOnDestroy() {
this.destroyed$.next()
this.destroyed$.complete()
}
this.store.pipe(select(userProfile)).pipe(
takeUntil(this.destroyed$),
... rest of RxJS stream and subscription
);