2017-03-01 8 views
4

エラーを処理する方法をAngular2ルートガードは、私のようなルートガードを持って

@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-インターセプタを持っている以下ログインページにリダイレクトします。この問題は、HTTP要求がエラーをスローし、角度ルータがこの最初のルーティング要求でスタックし、インターセプタからの後続の要求を処理できないため、このマップが決して解決しないことです。このエラーを処理し、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; 
    } 

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

は、あなたがして/ getAuthenticatedUserからの応答をキャッチしていないでしょうか? http://stackoverflow.com/questions/23559341/using-success-error-finally-catch-with-promises-in-angularjs –

+0

あなたが意味するものを表示して、参照用にhttp-intercepterとgetAuthenticatedUser()を追加しました – Josh

答えて

6

以下のhttp-intercepterあなたがエラーをキャッチし、次のように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); 
     }); 
} 
+0

これは最初に試したことはありますが、それは決してキャッチにヒットしません – Josh

+0

あなたの問題はおそらくインターセプターにあります。 –

+0

私はそうは思わない、それはルータrouter.navigateを呼び出して元のエラーをスローする、私は質問内容にそれを加えた – Josh

関連する問題