输入 url 时 canActivate 不起作用
canActivate not working when url is typed
基本上一切正常,直到由于某种原因输入 url 方法 canActivate 中的变量 this.estado 恰好未定义。
我认为这是因为构造函数没有在正确的时间获取可观察对象。
import { Component, Injectable, Inject, OnInit } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class AuthService implements CanActivate {
myAppUrl: string;
estado: any;
constructor(private router: Router, private http: HttpClient, @Inject('BASE_URL') private baseUrl: string) {
this.myAppUrl = baseUrl;
this.estadoSetUp(); /* If I put hear this.estado = true everything works fine */
}
public getJSON(): Observable<any> {
return this.http.get(this.myAppUrl + 'api/IsAuthenticated');
}
public estadoSetUp() {
this.getJSON().subscribe(data => {
this.estado = data.AmILoggin;
});
}
canActivate(): Observable<boolean> {
if (this.estado != true) {
this.router.navigate(['/']);
}
return this.estado;
}
}
已解决,感谢@sirdieter
我在这里留下解决方案,以供将来遇到麻烦的任何人使用:
import { Component, Injectable, Inject, OnInit } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject'
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
@Injectable()
export class AuthService implements CanActivate {
myAppUrl: string;
private isAuthorized = new ReplaySubject<boolean>(1);
constructor(private router: Router, private http: HttpClient, @Inject('BASE_URL') private baseUrl: string) {
this.myAppUrl = baseUrl;
this.estadoSetUp();
}
public getJSON(): Observable<any> {
return this.http.get(this.myAppUrl + 'api/IsAuthenticated');
}
public estadoSetUp() {
this.getJSON().subscribe(data => {
this.isAuthorized.next(data.AmILoggin);
});
}
canActivate(): Observable<boolean> {
return this.isAuthorized.asObservable()
.do(auth => {
if (auth != true) {
this.router.navigate(['/']);
}
});
}
}
请注意您的 http 调用是异步的,
因此,当您直接打开 URL 时,会构建此守卫(它会启动 http 调用),并在此之后不久(毫秒)调用 "canActivate"。
因此,如果您的 http 调用不够快,则您的变量未定义,因为没有来自 http 调用的结果。
canActivate returns 布尔值的 Observable。因此,一种解决方案是将您的变量 estado 更改为 observable
您正确地发现了问题。
您可以 return 可观察到的 http 调用并将其映射到 AmILoggin 属性。
(RxJS 6 Syntax, 你好像有5个)
canActivate(): Observable<boolean> {
return this.getJSON().pipe(pluck('AmILoggin');
}
但在这种情况下,每次调用 canActivate() 时,您都会进行 http 调用;
要只进行一个 http 调用,您可以使用主题:
private isAuthorized = new ReplaySubject<boolean>(1);
public estadoSetup() {
this.getJSON().subscribe(data => this.isAuthorized.next(data.AmILoggin));
}
// RxJS 6
canActivate() {
return this.isAuthorized.asObservable().pipe(
tap(auth => {
if (auth) {
this.router.navigate(['/']);
}
}
);
}
// RxJS 5
canActivate(): Observable<boolean>
return this.isAuthorized.asObservable()
.do(auth => {
if (auth) {
this.router.navigate(['/']);
}
});
基本上一切正常,直到由于某种原因输入 url 方法 canActivate 中的变量 this.estado 恰好未定义。
我认为这是因为构造函数没有在正确的时间获取可观察对象。
import { Component, Injectable, Inject, OnInit } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class AuthService implements CanActivate {
myAppUrl: string;
estado: any;
constructor(private router: Router, private http: HttpClient, @Inject('BASE_URL') private baseUrl: string) {
this.myAppUrl = baseUrl;
this.estadoSetUp(); /* If I put hear this.estado = true everything works fine */
}
public getJSON(): Observable<any> {
return this.http.get(this.myAppUrl + 'api/IsAuthenticated');
}
public estadoSetUp() {
this.getJSON().subscribe(data => {
this.estado = data.AmILoggin;
});
}
canActivate(): Observable<boolean> {
if (this.estado != true) {
this.router.navigate(['/']);
}
return this.estado;
}
}
已解决,感谢@sirdieter
我在这里留下解决方案,以供将来遇到麻烦的任何人使用:
import { Component, Injectable, Inject, OnInit } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject'
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
@Injectable()
export class AuthService implements CanActivate {
myAppUrl: string;
private isAuthorized = new ReplaySubject<boolean>(1);
constructor(private router: Router, private http: HttpClient, @Inject('BASE_URL') private baseUrl: string) {
this.myAppUrl = baseUrl;
this.estadoSetUp();
}
public getJSON(): Observable<any> {
return this.http.get(this.myAppUrl + 'api/IsAuthenticated');
}
public estadoSetUp() {
this.getJSON().subscribe(data => {
this.isAuthorized.next(data.AmILoggin);
});
}
canActivate(): Observable<boolean> {
return this.isAuthorized.asObservable()
.do(auth => {
if (auth != true) {
this.router.navigate(['/']);
}
});
}
}
请注意您的 http 调用是异步的,
因此,当您直接打开 URL 时,会构建此守卫(它会启动 http 调用),并在此之后不久(毫秒)调用 "canActivate"。 因此,如果您的 http 调用不够快,则您的变量未定义,因为没有来自 http 调用的结果。
canActivate returns 布尔值的 Observable。因此,一种解决方案是将您的变量 estado 更改为 observable
您正确地发现了问题。 您可以 return 可观察到的 http 调用并将其映射到 AmILoggin 属性。 (RxJS 6 Syntax, 你好像有5个)
canActivate(): Observable<boolean> {
return this.getJSON().pipe(pluck('AmILoggin');
}
但在这种情况下,每次调用 canActivate() 时,您都会进行 http 调用; 要只进行一个 http 调用,您可以使用主题:
private isAuthorized = new ReplaySubject<boolean>(1);
public estadoSetup() {
this.getJSON().subscribe(data => this.isAuthorized.next(data.AmILoggin));
}
// RxJS 6
canActivate() {
return this.isAuthorized.asObservable().pipe(
tap(auth => {
if (auth) {
this.router.navigate(['/']);
}
}
);
}
// RxJS 5
canActivate(): Observable<boolean>
return this.isAuthorized.asObservable()
.do(auth => {
if (auth) {
this.router.navigate(['/']);
}
});