我了解到,通常您不必明确地退出Router
或ActivatedRoute
的订阅,因为:
ActivatedRoute及其可观察物与路由器绝缘 本身。当路由组件不再存在时,它会销毁它 需要,注入的ActivatedRoute随之死亡。
来源:Do I have to unsubscribe from ActivatedRoute (e.g. params) observables?
但是,我在父组件subscribe()
中反复在ActivatedRoute.firstChild.paramMap
上调用app.component
。仅当用户离开Web应用程序或关闭网站时,此组件才会被销毁,因此我担心那些paramMap
订阅可能会一直保持活动状态。
订阅调用在Router.events
订阅中进行,如下所示:
this.routerSubscription = this.router.events
.pipe(
tap((event) => {
switch (true) {
case event instanceof NavigationStart: {
setTimeout(() => this.showChildComponentLoading = true);
break;
}
case event instanceof NavigationEnd:{
this.activatedRoute.firstChild.paramMap.subscribe(paramMap => {
if(paramMap.has('mode')){
let newWebAppMode:string = paramMap.get('mode');
if(this.dataStoreService.isValidWebAppMode(newWebAppMode) && newWebAppMode !== this.dataStoreService.currentAppMode)
this.saveToLocalStorage.next([DataType.WEB_APP_MODE, newWebAppMode]);
}
});
//other code
每次有人导航到另一个组件/页面activatedRoute.firstChild.paramMap
时,都会再次订阅。我仅在事件为NavigationEnd
的实例时才在路由器订阅中执行此操作,因为在此之前url参数尚不可用。
我的问题是,这些订阅会如何处理?他们是自动退订还是我需要手动退订每个新的?如果是后者,我该如何有效地做到这一点?
有些人可能建议我使用activatedRoute.firstChild.snapshot.paramMap.myParameter
,因为那样我就不必订阅任何东西。但是,在重用相同组件的同时url参数更改时,snapshot
不起作用。所以我不能使用它。
谢谢
答案 0 :(得分:1)
是的,它看起来确实像是潜在的内存泄漏:每个NavigationEnd
上都会产生一个新订阅,因此您可能无限制地拥有相同流的相同观察者(并且activatedRoute.firstChild.paramMap
会无限期地发出)。您可以通过在订阅中放入简单的console.log(new Date())
来进行验证。
我相信switchMap
是您的朋友(订阅新流后,它会自动从旧流中退订)。像
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
switchMap(() => this.activatedRoute.firstChild.paramMap),
filter(paramMap => paramMap.has('mode')),
map(paramMap => paramMap.get('mode')),
filter(newMode => this.dataStoreService.isValidWebAppMode(newMode) &&
newMode !== this.dataStoreService.currentAppMode),
).subscribe(newMode => this.saveToLocalStorage.next([DataType.WEB_APP_MODE, newMode]);
顺便说一句,您是否需要防止this.activatedRoute.firstChild
为空?
答案 1 :(得分:0)
在这些情况下无需退订
在HttpClient调用的情况下,因为可观察对象发出一个值(成功或错误)并自动完成。
以防万一或ActivatedRoute预订,因为当组件自动销毁时,路由器会销毁它
使用异步管道