Что может произойти, если вы не отмените подписку на Observable в canActivate of guard? - PullRequest
2 голосов
/ 06 января 2020

Пожалуйста, посмотрите пример ниже

import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
import {Observable, of} from 'rxjs';
import {Injectable} from '@angular/core';
import {AuthService} from './auth.service';
import {map, take} from 'rxjs/operators';

@Injectable({providedIn: 'root'})
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService,
              private router: Router) {
  }
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> | Observable<boolean | UrlTree> | boolean {
    return this.authService.user.pipe(
      take(1),
      map(user => {
        if (!!user) {
          return true;
        }
        return this.router.createUrlTree(['/auth']);
      }));
  }
}

user имеет тип BehaviorSubject, и он определяет статус авторизации пользователя, то есть если он равен объекту, то пользователь залогинен, а не иначе. Поэтому охранник активирует маршрут /auth, если пользователь вошел в систему, и перенаправляет нас в противном случае. Теперь, что произойдет, если я удалю take(1) из конвейера, чтобы в результате мы не отписались?

Ответы [ 2 ]

2 голосов
/ 06 января 2020

Думаю, беспокоиться не о чем. Насколько я вижу, каждый раз, когда canActivate охранник запускается с помощью first(), он автоматически отписывается от возвращаемой наблюдаемой.

check_guard.ts

function runCanActivate(
    futureRSS: RouterStateSnapshot, futureARS: ActivatedRouteSnapshot,
    moduleInjector: Injector): Observable<boolean|UrlTree> {
  const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
  if (!canActivate || canActivate.length === 0) return of (true);

  const canActivateObservables = canActivate.map((c: any) => {
    return defer(() => {
      const guard = getToken(c, futureARS, moduleInjector);
      let observable;
      if (isCanActivate(guard)) {
        observable = wrapIntoObservable(guard.canActivate(futureARS, futureRSS));
      } else if (isFunction<CanActivateFn>(guard)) {
        observable = wrapIntoObservable(guard(futureARS, futureRSS));
      } else {
        throw new Error('Invalid CanActivate guard');
      }
      return observable.pipe(first()); // <----------- Here!
    });
  });
  return of (canActivateObservables).pipe(prioritizedGuardValue());
}
2 голосов
/ 06 января 2020

Ничего не произойдет, ваше поведение будет сохранено. Я предполагаю, что этот вопрос больше ориентирован на «стоимость» отказа от подписки.

Под капотом angular добавляет оператор first к наблюдаемому, который завершает наблюдаемое после испускания первое значение.

Это было добавлено к этому PR

...