0

Router通常、次の理由により、またはActivatedRoute明示的に購読を解除する必要はないことを読みました。

ActivatedRoute とそのオブザーバブルは、ルーター自体から隔離されています。Router はルーティングされたコンポーネントが不要になったときにそれを破棄し、注入された ActivatedRoute も一緒に終了します。

ソース: ActivatedRoute (例: params) オブザーバブルからサブスクライブを解除する必要がありますか?

ただし、親コンポーネントsubscribe()で繰り返し呼び出しています。このコンポーネントは、ユーザーが Web アプリケーションから移動するか、Web サイトを閉じたときにのみ破棄されるため、これらのサブスクリプションがずっとアクティブなままになるのではないかと心配しています。ActivatedRoute.firstChild.paramMapapp.componentparamMap

サブスクリプション呼び出しはサブスクリプション内で行われ、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何もサブスクライブする必要がないので、使用するようにアドバイスする人もいるかもしれません。ただし、snapshot同じコンポーネントを再利用しているときに url パラメータが変更された場合は機能しません。だから私はそれを使用することはできません。

ありがとうございました

4

2 に答える 2

2

はい、それは潜在的なメモリ リークのように見えます: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ところで、 nullになることを防ぐ必要はありませんか?

于 2020-07-06T21:30:36.370 に答える