簡體   English   中英

如何在帶有角度的canActivate中調用異步方法?

[英]How to call an async method in canActivate with angular?

我正在嘗試為Angular 4.2.4中的管理路由實現canActivate保護。

基於此堆棧問題: canActivate Question ,我認為我做的一切正確。 但是,a,我似乎無法使事情正常進行。

這是模塊防護:

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private _store: Store<AppState>,
              private router: Router,
              private czauth: CzauthService) { }

  canActivate(route: ActivatedRouteSnapshot):Observable<boolean>{
    return this.czauth.verifyAdminUser().first();
  }
};

這是我的czauth服務:

  getToken():Observable<firebase.User>{
    return this.af.idToken;
  }

  verifyUserRole(token){
      this.token = token;
      console.log(token);// Log out "PromiseObservable {_isScalar: false, promise: D, scheduler: undefined}"
      let headers = new Headers({ 'Authorization': 'Bearer ' + token});
      let options = new RequestOptions({ headers: headers });
      return this.http.get(environment.api+'/verifyadminuser', options).map((response)=>{return response.json()});
  }


  verifyAdminUser():Observable<boolean>{
    return this.getToken()
      .map((user)=>{return Observable.fromPromise(user.getIdToken())})
      .map((token)=>{return this.verifyUserRole(token)})
      .do((response)=>{console.log(response)})// Always returns "Observable {_isScalar: false, source: Observable, operator: MapOperator}"
      .switchMap((response:any)=>{ return response.status === 200 ? Observable.of(true) : Observable.of(false)});
  }

我永遠無法從我的http異步調用獲得響應。 在控制台中,我總能感覺到寒冷。 好像路由器從不訂閱我的觀察者嗎? 我想根據我的http響應返回一個布爾值。 我該如何實現?

編輯:

我正在從警衛人員調用verifyAdminUser方法。 該服務是根模塊上的一個模塊。 防護措施可保護對延遲加載的模塊的訪問。

下面,我列出了在路由中使用保護的位置。

路由模塊:

const routes: Routes = [
  {path: '', loadChildren : './landing/landing.module#LandingModule'},
  {path: 'dashboard', loadChildren : './dashboard/dashboard.module#DashboardModule', canActivate: [ AuthGuard ]}
];

@NgModule({
  imports: [RouterModule.forRoot(routes, {preloadingStrategy: PreloadAllModules})],
  exports: [RouterModule]
})
export class AppRoutingModule { }

問題是當用戶嘗試導航到儀表板模塊時,canActivate始終返回false,因為在switchMap運算符中的響應未定義。

編輯2:

我在代碼中重構並簡化了以下兩種方法,現在一切正常。 現在,我試圖了解原因。 以下是調整后的方法:

  verifyUserRole(){
      let headers = new Headers({ 'Authorization': 'Bearer ' + this.token});
      let options = new RequestOptions({ headers: headers });
      return this.http.get(environment.api+'/verifyadminuser', options).map((response)=>{return response});
  }


  verifyAdminUser():Observable<boolean>{
    return this.getToken()
      .map((user)=>{
        user.getIdToken().then((token)=>this.token = token);
        return user;
      })
      .map(()=>{return this.verifyUserRole})
      .switchMap((response:any)=>{ return response ? Observable.of(true) : Observable.of(false)});
  }

解:

感謝下面的@BeetleJuice出色答案,我得以創建一個派生解決方案。 這是我重構的兩種方法:

  verifyUserRole(token){
    this.token = token;
    let headers = new Headers({ 'Authorization': 'Bearer ' + token});
    let options = new RequestOptions({ headers: headers });
    return this.http.get(environment.api+'/verifyadminuser', options).map((response)=>{return response});
  }


  verifyAdminUser():Observable<boolean>{
    return this.getToken()
      .switchMap((user)=>{return Observable.fromPromise(user.getIdToken())})
      .switchMap((token)=>{return this.verifyUserRole(token)})
      .map((response:any)=>{ return response.status === 200 ? true : false});
  }

注意此行,取自verifyUserRole

console.log(token);// Log out "PromiseObservable...

因此token是可以觀察到的,但是您在下一行將其視為字符串,因此服務器可能會拒絕該請求

let headers = new Headers({ 'Authorization': 'Bearer ' + token})

您正在濫用verifyAdminUser().map運算符。 map僅應與同步功能一起使用。 例如:

// this works if user.id is a property available immediately
return this.getToken().map(user => user.id)

map不應與異步函數一起使用。 例如:

// this fails since the return value is an Observable that will resolve later
return this.getToken().map(user => Observable.fromPromise(...))

map立即返回。 結果,沿着鏈條傳遞的不是您期望的令牌本身,而是將來會生成令牌的Observable。 這就是為什么console.log(token)給您“ PromiseObservable”的原因。 您需要的是一個運算符,它將等待其中的可觀察值產生,然后將發出的值傳遞給下一個運算符。 使用switchMap

//this will work; switchMap waits for Obervable.fromPromise 
// to emit before continuing
return this.getToken().switchMap(user => Observable.fromPromise(...))

因此,基本上,代替mapswitchMap在線3和4 verifyAdminUser 您還可以通過執行相反的verifyAdminUser來簡化verifyAdminUser的最后一行:

.switchMap((response:any)=>{ return response.status === 200 ? Observable.of(true) : Observable.of(false)})

// no need for switchMap because response.status is available immediately
.map(res => res.status===200? true: false)

另外,您使用的canActivate錯誤。 這是為了防止激活組件。 為防止加載延遲加載的模塊,請使用canLoad保護。 所以我想要么更換canActivatecanLoad (如果我要保護整個模塊),或移動canActivate后衛到具有特定的路線component:內財產DashboardRoutingModule (我猜的名字)

查看文件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM