web-dev-qa-db-ja.com

Angular2ルートガードがObservable <bool>を返す、エラーの処理方法

以下のようなルートガードがいます

@Injectable()
export class AuthGuard implements CanActivate {

constructor(private router: Router, private authenticationSvc: AuthenticationService) { }

canActivate(): Observable<boolean> {
    return this.authenticationSvc.getAuthenticatedUser().map(
        r => {
            if (this.authenticationSvc.isAuthenticated()) {
                // logged in so return true
                return true;
            }
            this.router.navigateByUrl('/login');
            return false;
        })
}

問題は、getAuthenticatedUserが401を返すことがあり、401を処理してログインページにリダイレクトするhttp-interceptorがあることです。問題は、httpリクエストがエラーをスローし、angularルーターがこの最初のルーティングリクエストでスタックし、インターセプターからの後続のリクエストを処理できないため、この.mapが解決されないことです。方法このエラーを処理して、Observableをfalseに解決して、処理を続行できますか?

  getAuthenticatedUser() {
         let getUserObservable = this.http.get(ApiUrl + 'security/getAuthenticatedUser')
            .map((res: any) => res.json())
            .share()

        //Get the result for the cache
        getUserObservable.subscribe(
            r => {
                if (r.success) {
                    this.authenticatedUser = r.result.user;
                }
            }); 

        //return the observable
        return getUserObservable;
  } 

以下のhttp-intercepter

export class HttpInterceptor extends Http {
    authSvc: AuthenticationService;
    lastClicked: any = 0;
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router, private injector: Injector) {
        super(backend, defaultOptions);
    }
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.request(url, options));
}

get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.get(url, options));
}

post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
}

put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
}

delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.delete(url, options));
}

getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
    if (options == null) {
        options = new RequestOptions();
    }
    if (options.headers == null) {
        options.headers = new Headers();
    }
    options.headers.append('Content-Type', 'application/json');
    return options;
}

 intercept(observable: Observable<Response>): Observable<Response> {
    return observable.catch((err, source) => {
        //If we get a 401 from the api that means out FormsAuthenticationTicket has expired, clear the auth cookie and navigate back to terms page
        if (err.status == 401) {
            this._router.navigateByUrl('/login');
        }

        return Observable.throw(err);
    });
}
8
Josh

次のように、エラーをキャッチしてObservable<bool>を返すことができます。

@Injectable()
export class AuthGuard implements CanActivate {

constructor(private router: Router, private authenticationSvc: AuthenticationService) { }

canActivate(): Observable<boolean> {
    return this.authenticationSvc.getAuthenticatedUser().map(
        r => {
            if (this.authenticationSvc.isAuthenticated()) {
                // logged in so return true
                return true;
            }
            this.router.navigateByUrl('/login');
            return false;
        })
        .catch((error: any) => {
            this.router.navigateByUrl('/login');
            return Observable.of(false);
        });
}
8
Seid Mehmedovic