Please, see an example below
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']);
}));
}
}
The user is of type BehaviorSubject, and it defines an authorization status of an user, that is if it is equal to an object, then an user is logged in, and not otherwise. Therefore, the guard activates /auth route if the user is logged in, and it redirects us otherwise.
Now, what will happen if I remove take(1) from the pipeline so that we do not unsubscribe as a result?
Nothing will happen, the same behaviour you experience will be preserved. I guess this question is angled more towards the "cost" of not unsubscribing.
Under the hood, angular adds the first operator to the observable, which completes the observable after emitting the first value.
This was added on this PR
I think there is nothing to worry about.
As far as I can see, every time a canActivate guard is run, by using first(), it will automatically unsubscribe from the returned observable.
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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With