page navigationend change angular2 angular angular2-routing angular2-http

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; }); }