2017-03-01 62 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