2017-03-01 58 views
4

我有一個路線警衛像下面Angular2路線警衛返回可觀察<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,和我有一個HTTP的攔截器,處理401和重定向到登錄頁面。問題是,這個.map永遠不會解析,因爲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-截擊你可以找出錯誤並返回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

這是我試過的第一件事,但它從來沒有碰到catch – Josh

+0

然後你的問題是與攔截器,最有可能的。 –

+0

我不這麼認爲,它所做的只是調用router.navigate,然後拋出原始錯誤,我將其添加到問題內容 – Josh