2017-10-26 5 views
0

私はAngular 4 Webアプリケーションを作成しています。私はAuthGuardCanActivateを使ってルートを保護する必要があるので、ユーザーが特定のルートにアクセスできるかどうかを確認します。AuthGuardは、関数の終了まで有効化し、サブスクリプションがtrueを返すのを待つ代わりにfalseを返します。

CanActivateは、idsessionStorageにあるかどうか最初にチェックします。それ以外の場合は、ユーザーが承認されている場合にバックエンドを確認します。 idが既にsessionStorageにあるプロジェクトをクリックしてcheckIfIDInStorageに入りますが、それがelseに入り、自分のAPIを呼び出すと、関数の最後に移動して呼び出し前にfalseを返しますtrueを返しますcanActivatereturn falseを削除すると、それでも機能しません。私がそれが本当に戻ってきたことを確認した後、私は再びプロジェクトをクリックするとうまくいきます。

コンソール出力

can activate else 
before return false 
in subscribe if 
true 
in store 

Guard.ts

canActivate (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean 
{ 
    const id = route.params.id; 
    if (this.checkIfIDInStorage(id)) { 
    console.log("checking id"); 
    return true; 
    } 
    else { 
    console.log("in can activate else"); 
    this.API.checkProjectOwnership(id).subscribe((data) => 
    { 
     console.log("in subscribe if"); 
     if (data.type === 'AL') { 
     console.log("true"); 
     this.storeProjectID(id); 
     return true; 
     } 
     else { 
     console.log("in subscribe else "); 
     this.router.navigate(['/dashboard']); 
     } 
    }); 
    } 
    console.log("before return false"); 
    return false; 
} 

storeProjectID(id: string) { 
    console.log("in store"); 
    this.session.store('id', id); 
    return true; 
} 

getProjectID() { 
    return this.session.retrieve('id'); 
} 

checkIfIDInStorage(id: string) { 
    const storedID = this.getProjectID(); 
    return (id === storedID); 
} 

API.service.ts

checkProjectOwnership(params: URLSearchParams): Observable<any> { 
    const URL = `${this.API}/projects/ownership?id=${params}`; 
    return this.auth.refreshToken() 
     .flatMap(() => this.authHttp.get(URL, this.headers)) 
     .map((response: Response) => response.json()) 
     .share() 
     .catch(this.handleError); 
    } 
+1

これは、API呼び出しが非同期であるためです。この関数は、非同期呼び出しが終了するのを待機しません。代わりにルートリゾルバを使用してみることもできます。 *あなたの非同期API呼び出しを待ちます。または、あなたのガードをここに示すようにBooleanの代わりにObservableを返すようにすることができます:https://stackoverflow.com/questions/38425461/angular2-canactivate-calling-asyncfunction – DeborahK

答えて

0

私は、観察を返すことによってそれを解決することができました。

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean 
{ 
    const id = route.params.id; 
    return new Observable<boolean>((observer) => 
    { 
    if (this.checkIfIDInStorage(id)) { 
     observer.next(true); 
     observer.complete(); 
    } 
    else { 
     const params = new URLSearchParams(); 
     params.append('id', id); 
     this.API.checkProjectOwnership(id).subscribe((data) => 
     { 
      console.log("in subscribe if"); 
      if (data.type === 'AL') { 
      this.storeProjectID(id); 
      observer.next(true); 
      observer.complete(); 
      } 
      else { 
      this.router.navigate(['/dashboard']); 
      observer.next(false); 
      observer.complete(); 
      return false; 
      } 
     }); 
    } 
    }); 
} 
関連する問題