2016-12-05 154 views
3

我有一个非常简单的服务,它的工作是从API获得200或401 /验证网址。角2 ngIf可观察?

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> 

如果401是从未来的HandleError然后隐藏否则显示的股利。

它就像从可观测得到的布尔值。我也有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,因为订阅需要时间。

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 地图 和未经授权的:401 捕捉

+0

此ngIf从哪里来?我假定的组件?拥有该组件的'.ts'会很好。 – Maxime

+0

如果你不'订阅'observable,你永远不会有任何结果。 – Maxime

+0

最后,一旦你有一个组件取得一个http调用的结果(来自一个服务),你可以订阅它并保存该值以显示它到你的视图中,或者使用'async'管道。 – Maxime

回答

7

在这里,你正在返回可观察到的,而不是价值:

authenticateUser(): Observable<any> { 
    return this.http.get(AppSettings.authenitcationEnpoint) 
     .map(this.extractData) 
     .catch(this.handleError); 
} 

什么你应该做的是建立在服务的属性,然后使用你的HTML订阅了可观察此属性,而不是功能。喜欢的东西:

@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管的另一种方式。因此,视图将等待观察返回之前返回消化cicle。例如:

<div *ngIf="authService.AuthenticateUser() | async">my content</div> // Here you use the async pipe 
+0

因为如果值发生变化,它不会被更新。这是可观察的主要兴趣。 – Maxime

+0

@Maxime它不会被更新?你为什么这么说? – vinagreti

+0

Arf这不是我的意思,我的确不好。他将无法认同该价值的变化。在这种情况下以及在一般情况下太糟糕了。如果他有一个可观察的他应该保留它:) – Maxime