navigationend - router events subscribe angular 4
Angular 2-Enrutamiento-Puede activar el trabajo con Observable (8)
¿Cómo funciona para usted sin llamar a suscribirse? para mí, cuando llamo a esto a través de mi API .net, nada vuelve Tengo que llamar a suscribirme en mi servicio de protección de autenticación de esta manera, solo que realiza una llamada API real. Pero dado que la suscripción es asíncrona, mi canActivate guard no funciona y el usuario puede ingresar a la página.
AuthGauard service:
canActivate() { this.loginService.isLoggedIn()
.subscribe(response => {
if (!response) return false;})
return true;
}
loginService:
isLoggedIn():Observable<boolean> {
return this.http.get(ApiResources.LOGON).pipe(map(response => response.ok));
}
Tengo un AuthGuard (usado para enrutamiento) que implementa CanActivate .
canActivate() {
return this.loginService.isLoggedIn();
}
Mi problema es que CanActivate-result depende de un http-get-result: LoginService devuelve un Observable .
isLoggedIn():Observable<boolean> {
return this.http.get(ApiResources.LOGON).map(response => response.ok);
}
¿Cómo puedo unirlos? ¿Hacer que CanActivate dependa de un estado de fondo?
Actualización de la respuesta de Kery Hu para Angular 5 y RxJS 5.5
donde el operador de
catch
está en desuso.
Ahora debe usar el operador catchError junto con los
operadores
pipe
y
lettable
.
import { Injectable } from ''@angular/core'';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from ''@angular/router'';
import { Observable } from ''rxjs/Observable'';
import { catchError, map} from ''rxjs/operators'';
import { of } from ''rxjs/observable/of'';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private loginService: LoginService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.loginService.isLoggedIn().pipe(
map(e => {
if (e) {
return true;
} else {
...
}
}),
catchError((err) => {
this.router.navigate([''/login'']);
return of(false);
})
);
}
}
CanActivate funciona con Observable pero falla cuando se realizan 2 llamadas como CanActivate: [Guard1, Guard2].
Aquí, si devuelve un Observable de falso desde Guard1, también se registrará en Guard2 y permitirá el acceso a la ruta si Guard2 devuelve verdadero.
Para evitar eso, Guard1 debería devolver un booleano en lugar de Observable de booleano.
Debería actualizar "@ angular / router" a la última versión. por ejemplo, "3.0.0-alpha.8"
modificar AuthGuard.ts
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private loginService:LoginService, private router:Router) { }
canActivate(next:ActivatedRouteSnapshot, state:RouterStateSnapshot) {
return this.loginService.isLoggedIn().map(e => {
if (e) {
return true;
}
}).catch(() => {
this.router.navigate([''/login'']);
return Observable.of(false);
});
}
}
Si tienes alguna pregunta, pregúntameļ¼
Esto puede ayudarte
import { Injectable } from ''@angular/core'';
import { CanActivate, Router } from ''@angular/router'';
import { Select } from ''@ngxs/store'';
import { Observable } from ''rxjs'';
import { map, take } from ''rxjs/operators'';
import { AuthState } from ''src/app/shared/state'';
export const ROLE_SUPER = ''ROLE_SUPER'';
@Injectable()
export class AdminGuard implements CanActivate {
@Select(AuthState.userRole)
private userRoles$: Observable<string[]>;
constructor(private router: Router) {}
/**
* @description Checks the user role and navigate based on it
*/
canActivate(): Observable<boolean> {
return this.userRoles$.pipe(
take(1),
map(userRole => {
console.log(userRole);
if (!userRole) {
return false;
}
if (userRole.indexOf(ROLE_SUPER) > -1) {
return true;
} else {
this.router.navigate([''/login'']);
}
return false;
})
);
} // canActivate()
} // class
Lo he hecho de esta manera:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.userService.auth(() => this.router.navigate([''/user/sign-in'']));}
Como puede ver, estoy enviando una función alternativa a userService.auth qué hacer si falla la llamada http.
Y en userService tengo:
import ''rxjs/add/observable/of'';
auth(fallback): Observable<boolean> {
return this.http.get(environment.API_URL + ''/user/profile'', { withCredentials: true })
.map(() => true).catch(() => {
fallback();
return Observable.of(false);
});}
en canActivate (), puede devolver una propiedad booleana local (predeterminada en falso en su caso).
private _canActivate: boolean = false;
canActivate() {
return this._canActivate;
}
Y luego, en el resultado de LoginService, puede modificar el valor de esa propiedad.
//...
this.loginService.login().subscribe(success => this._canActivate = true);
angular.io/docs/ts/latest/api/router/index/…
acepta
Observable<boolean>
como valor devuelto.
El guardia esperará a que el Observable se resuelva y mirará el valor.
Si es ''verdadero'', pasará la verificación, de lo contrario (cualquier otro dato o error arrojado) rechazará la ruta.
Puede usar el operador
.map
para transformar el
Observable<Response>
en
Observable<boolean>
manera:
canActivate(){
return this.http.login().map((res: Response)=>{
if ( res.status === 200 ) return true;
return false;
});
}