Подписка на наблюдаемые в маршрутных охранниках и их последствия

У меня охранник роутера называется PermissionGuard который начинается здесь

const routes: Routes = [
  {
    path: ':company',
    component: CompanyComponent,
    canActivate: [PermissionGuard],
    canActivateChild: [PermissionGuard],
    children: [
      {
        path: '',
        component: IndexComponent
      },
      {
        path: 'projects',
        loadChildren: '../projects/projects.module#ProjectsModule'
      },
    ]
  }
];

Внутри моего PermissionGuard Я подписываюсь на PermissionService как это:

export class PermissionGuard implements CanActivate, CanActivateChild {

  private permissions: Permission[];

  constructor(private permissionService: PermissionService, private router: Router) {
    this.permissionService.permissions$.subscribe(
      (permissions: Permission[]) => {
        this.permissions = permissions;
      }
    );
  }

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    this.permissionService.getPermissions(next.paramMap.get('company'));
    return this.permissionService.permissionsFetchDone$
    .pipe(filter(x => x))
    .pipe(
      map(response => {
        if (this.permissions) {
          return true;
        } else {
          this.router.navigate(['/forbidden']);
        }
      })
    );
  }
}

и выполнить необходимое canActivate или же canActivateChild проверки на основе этих данных. От добавления console.log() и испуская новые данные из permissions$ внутри детских маршрутов я вижу, что наблюдаемая все еще активна, хотя охрана "использовалась" и маршрут активирован. Затем я ожидал, что он исчезнет, ​​когда я пойду на маршрут за пределами path: ':company'Однако охранник не уничтожен.

Это подводит меня к моему вопросу: правильно ли я делаю? Я хочу использовать охрану, чтобы проверить, есть ли у пользователя какие-либо разрешения, но в то же время я хочу выполнить HTTP-запрос на разрешения только один раз (при переходе к path: ':company' или любой из его детей). Я боюсь, что если я буду использовать такие охранники, это со временем замедлит все приложение из-за огромного количества наблюдателей.

1 ответ

Решение

испуская новые данные из прав доступа $ внутри дочерних маршрутов, я вижу, что наблюдаемая все еще активна, даже если охрана "использовалась" и маршрут активирован.

Прежде всего, permissions$ все еще активен, потому что вы никогда не отписались в своей охране. И угловой создает охрану как синглтон.

Даже если охранник не был одиночкой, на экземпляр охранника все еще ссылаются в подписке через this.permissionsи если ваша наблюдаемая существует как переменная в вашей службе аутентификации (которую я предполагаю, что она является одиночной), эта привязка также предотвратит сборку мусора.

Это подводит меня к моему вопросу: правильно ли я делаю? Я хочу использовать охрану, чтобы проверить, есть ли у пользователя какие-либо разрешения,

Вполне нормально подать запрос в вашей гвардии, например, для получения разрешений.

но в то же время я хочу выполнить HTTP-запрос на разрешения только один раз (при переходе к пути: ':company' или любому из его дочерних элементов).

Если вы хотите выполнить запрос только один раз, вам следует подумать об использовании shareReplay в вашей службе аутентификации, чтобы все будущие экземпляры, которые подключаются, использовали одинаковые ранее выданные значения.

Другие вопросы по тегам