私は非常にシンプルなサービスを持っており、その仕事はapi/authenticateurlから200または401を取得することです。
auth.service.ts
@Injectable()
export class AuthService {
constructor(private http: Http) {
}
authenticateUser(): Observable<any> {
return this.http.get(AppSettings.authenitcationEnpoint)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(response: Response) {
let body = response;
return body || {};
}
private handleError(error: Response) {
let errMsg: string;
if (error instanceof Response) {
errMsg = `${error.status} - ${error.statusText || ''}`;
} else {
errMsg = error.toString();
}
return Observable.throw(errMsg);
}
}
これをHTMLで使用したいのですが、サブスクライバーを作成でき、応答またはエラーコードに基づいて変数を設定できますが、問題は、コードをあちこちに複製する必要があることです。とてもシンプルにしたい
<div *ngIf="authService.AuthenticateUser()">my content</div>
HandleErrorから来ている401の場合は非表示にし、そうでない場合はdivを表示します。
Observableからブール値を取得するようなものです。 AuthGuardもあります。
authguard.ts
@Injectable()
export class AuthGuard implements CanActivate {
private isActive: boolean = true;
constructor(private authService: AuthService, private router: Router) {
}
canActivate(): boolean {
this.authService.authenticateUser()
.subscribe(() => {},
error => {
if (error.indexOf("401") >= 0) {
let link = ['contactus'];
this.router.navigate(link);
this.isActive = false;
}
});
return this.isActive;
}
}
NgIfでもauthGuard.canActive()を使用できません。コードを複製せずにそれを行う簡単な方法はありますか?サブスクライブには時間がかかるため、AuthGuardは毎回trueを返す必要があるため、AuthGuardが機能していないことは間違いありません。
app.component.ts
export class AppComponent {
private isAuthenticated: boolean = false;
constructor(private authService: AuthService,private authGuard: AuthGuard) {
this.authService.authenticateUser()
.subscribe(response => {
if (response.status == 200)
this.isAuthenticated = true;
},
error => {
if (error.indexOf("401") >= 0)
this.isAuthenticated = false;
});
}
}
home.component.ts
export class HomeComponent implements OnInit {
constructor(private http: Http, private authService: AuthService, private utilityService: UtilityService, private homeService: HomeService, private factoryService: FactoryService, private supplierService: SupplierService, private businessAreaService: BusinessAreaService, private router: Router) {
this.authService.authenticateUser()
.subscribe(response => {
if (response.status == 200)
this.isAuthenticated = true;
},
error => {
if (error.indexOf("401") >= 0)
this.isAuthenticated = false;
});
this.customData = new CustomData(http);
}
}
ご覧のとおり、重複したコードがたくさんあります。重複を避けようとしています。
APIを呼び出すと、Windows認証用のWindowsユーザー名/パスワードを入力するポップアップが表示されます。そのポップアップをキャンセルするまで、401を取得しません。メニューとホームコンポーネントを非表示にします。
私のサービスでは、応答:200 in mapおよびauthorized:401 in catch blockを取得します
ここでは、値ではなく、オブザーバブルを返しています。
authenticateUser(): Observable<any> {
return this.http.get(AppSettings.authenitcationEnpoint)
.map(this.extractData)
.catch(this.handleError);
}
あなたがすべきことは、あなたのサービスでプロパティを作成し、そしてあなたのhtmlでこのプロパティを使用することであり、observableをサブスクライブする関数ではありません。何かのようなもの:
@Injectable()
export class AuthService {
isAuthenticated: boolean = false; //The variable
constructor(private http: Http) {
}
authenticateUser(): Observable<any> {
return this.http.get(AppSettings.authenitcationEnpoint)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(response: Response) {
let body = response;
this.isAuthenticated = body.isAuthenticated; //here you assign a value to variable
return body || {};
}
private handleError(error: Response) {
let errMsg: string;
if (error instanceof Response) {
errMsg = `${error.status} - ${error.statusText || ''}`;
} else {
errMsg = error.toString();
}
return Observable.throw(errMsg);
}
}
そして、あなたのhtmlで、ただ使用してください:
<div *ngIf="authService.isAuthenticated">my content</div>
これを行う別の方法は、async
パイプを使用することです。したがって、ビューは、ダイジェストシクルを作成する前に観測が戻るのを待ちます。何かのようなもの:
<div *ngIf="authService.AuthenticateUser() | async">my content</div> // Here you use the async pipe