Angular 2 - 路由 - CanActivate 与 Observable 一起工作
Angular 2 - Routing - CanActivate work with Observable
我有一个 AuthGuard(用于路由)实现了 CanActivate。
canActivate() {
return this.loginService.isLoggedIn();
}
我的问题是,CanActivate-result 取决于 http-get-result - LoginService returns 和 Observable.
isLoggedIn():Observable<boolean> {
return this.http.get(ApiResources.LOGON).map(response => response.ok);
}
我如何将它们组合在一起 - 让 CanActivate 依赖于后端状态?
######
编辑:请注意,这个问题是从 2016 年开始的——使用了 angular/router 的早期阶段。
######
在 canActivate() 中,您可以 return 本地布尔值 属性(在您的情况下默认为 false)。
private _canActivate: boolean = false;
canActivate() {
return this._canActivate;
}
然后在LoginService的结果中,可以修改那个属性的值。
//...
this.loginService.login().subscribe(success => this._canActivate = true);
您应该将“@angular/router”升级到最新版本。例如,“3.0.0-alpha.8”
修改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);
});
}
}
有什么问题可以问我!
我是这样做的:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.userService.auth(() => this.router.navigate(['/user/sign-in']));}
如您所见,我正在向 userService.auth 发送回退函数,如果 http 调用失败该怎么办。
在 userService 中我有:
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);
});}
canActivate() 接受 Observable<boolean>
作为返回值。守卫将等待 Observable 解析并查看值。如果 'true' 它将通过检查,否则(任何其他数据或抛出的错误)将拒绝路由。
您可以使用 .map
运算符将 Observable<Response>
转换为 Observable<boolean>
,如下所示:
canActivate(){
return this.http.login().map((res: Response)=>{
if ( res.status === 200 ) return true;
return false;
});
}
CanActivate 确实可以与 Observable 一起工作,但是当像 CanActivate:[Guard1, Guard2] 这样的 2 次调用时失败。
在这里,如果您 return 来自 Guard1 的 Observable 为 false,那么它也会检查 Guard2 并允许访问路由,如果 Guard2 return 为真。
为了避免这种情况,Guard1 应该 return 布尔值而不是布尔值的 Observable。
正在更新 Kery Hu 对 Angular 5+ 和 RxJS 5.5 and 的回答。
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);
})
);
}
}
这可能对您有所帮助
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
我有一个 AuthGuard(用于路由)实现了 CanActivate。
canActivate() {
return this.loginService.isLoggedIn();
}
我的问题是,CanActivate-result 取决于 http-get-result - LoginService returns 和 Observable.
isLoggedIn():Observable<boolean> {
return this.http.get(ApiResources.LOGON).map(response => response.ok);
}
我如何将它们组合在一起 - 让 CanActivate 依赖于后端状态?
######
编辑:请注意,这个问题是从 2016 年开始的——使用了 angular/router 的早期阶段。
######
在 canActivate() 中,您可以 return 本地布尔值 属性(在您的情况下默认为 false)。
private _canActivate: boolean = false;
canActivate() {
return this._canActivate;
}
然后在LoginService的结果中,可以修改那个属性的值。
//...
this.loginService.login().subscribe(success => this._canActivate = true);
您应该将“@angular/router”升级到最新版本。例如,“3.0.0-alpha.8”
修改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);
});
}
}
有什么问题可以问我!
我是这样做的:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.userService.auth(() => this.router.navigate(['/user/sign-in']));}
如您所见,我正在向 userService.auth 发送回退函数,如果 http 调用失败该怎么办。
在 userService 中我有:
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);
});}
canActivate() 接受 Observable<boolean>
作为返回值。守卫将等待 Observable 解析并查看值。如果 'true' 它将通过检查,否则(任何其他数据或抛出的错误)将拒绝路由。
您可以使用 .map
运算符将 Observable<Response>
转换为 Observable<boolean>
,如下所示:
canActivate(){
return this.http.login().map((res: Response)=>{
if ( res.status === 200 ) return true;
return false;
});
}
CanActivate 确实可以与 Observable 一起工作,但是当像 CanActivate:[Guard1, Guard2] 这样的 2 次调用时失败。
在这里,如果您 return 来自 Guard1 的 Observable 为 false,那么它也会检查 Guard2 并允许访问路由,如果 Guard2 return 为真。
为了避免这种情况,Guard1 应该 return 布尔值而不是布尔值的 Observable。
正在更新 Kery Hu 对 Angular 5+ 和 RxJS 5.5
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);
})
);
}
}
这可能对您有所帮助
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