2016-09-12 68 views
4

我正在使用Observable<boolean>返回canActivate()。 爲測試設置了以下功能,並正確解決了組件顯示問題。Angular2 CanActivate後衛不能正常工作

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { 
    return Observable.from([{ admin: true }]).map(x => 
    { 
    if (x.admin) return true; 
    return false; 
    }); 
} 

但是,實際代碼的行爲是我留在登錄組件上,儘管控制檯輸出指示路由應該激活。上述測試唯一真正的區別是我打電話服務this.auth.isAdmin()而不是使用Observable.fromthis.auth.isAdmin()的結果是Observable<boolean>,其值爲true。

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { 
    const isAdmin$ = this.auth.isAdmin(); 
    return isAdmin$.map(x => 
    { 
    console.log('isAdmin returned ' + x); 
    if (!x) { 
     console.log('redirectToLogin'); 
     this.auth.redirectToLogin(state.url); 
     return false; 
    } else { 
     console.log('canActivate = true'); 
     return true; 
    } 
    }); 
} 

這裏是路由:

{ 
    path: 'admin', 
    canActivate: [AdminGuard], 
    children: [ 
    ...adminRoutes 
    ] 
}, 

這裏是我的控制檯輸出:

isAdmin returned false 
admin-guard.service.ts:27redirectToLogin 
auth.service.ts:36 navigating to stored path "/admin" 
auth.service.ts:21 Object {isAdmin: true, isPaid: false, $key: "xYFs8kMDpKdYKxDw4AL21FtnSWn1"} 
admin-guard.service.ts:25 isAdmin returned true 
admin-guard.service.ts:31 canActivate = true 

這裏是萬一isAdmin()函數感興趣:

isAdmin(): Observable<boolean> { 
    if (!this.auth) return Observable.from([false]); 
    const uid = this.auth.uid; 
    return this.af.database.object(`user/${uid}`).do(x => console.log(x)).map(x => x.isAdmin); 
} 

回答

7

您的isAdmin函數返回的可觀察項未完成。 AngularFire2 FirebaseObjectObservable實例不完整;隨着底層數據的變化,它們會發出對象。

守衛返回的觀察物必須完成。您可以通過使用first(或take(1))時,第一個值發射完成觀察的確保這一點:

canActivate(
    route: ActivatedRouteSnapshot, 
    state: RouterStateSnapshot 
): Observable<boolean> { 
    const isAdmin$ = this.auth.isAdmin(); 
    return isAdmin$.first().map(x => 
    { 
    console.log('isAdmin returned ' + x); 
    if (!x) { 
     console.log('redirectToLogin'); 
     this.auth.redirectToLogin(state.url); 
     return false; 
    } else { 
     console.log('canActivate = true'); 
     return true; 
    } 
    }); 
} 

在寫作的時候,有必要爲返回觀察到的完成。然而,Angular現在在返回的observable上調用first,所以不再需要完成observable。

+0

工程就像一個魅力,謝謝! –