2017-08-25 52 views
1

觀察值我遵循了很多教程,並嘗試了許多組合,但無法使這項工作。Angular 4:無法訂閱從CanActivate AccessGuard

我需要在用戶登錄時讓路由可用。如果他不是我需要將他重定向到主頁(this._popupService.setCallbackRoute(route.url.join('/')))並顯示一個彈出窗口(this._popupService.showPopUp()),讓他登錄或註冊。

我無法從authService獲取syncronized值。這是我的代碼:

app.module.ts

imports: [ 
    BrowserModule, 
    FormsModule, 
    HttpModule, 
    RouterModule.forRoot(
     {path: '', component: HomepageComponent}, 
     { 
      path: 'protectedRoute', 
      component: SubmitComponent, 
      data: {requiresLogin: true}, 
      canActivate: [AccessGuard] 
     } 
    ), 
    ... 
] 

auth.service.ts

@Injectable() 
export class AuthService { 

    private loggedIn: Subject<boolean> = new Subject<boolean>(); 

    get isLoggedIn() { 
     return this.loggedIn.asObservable(); 
    } 

    login(user: IUser) { 
     return this._http.get('assets/api/responseSuccess.json?email=' + user.email + '&password=' + user.password) 
      .map((responseLogin => { 
       const jsonResponse = responseLogin.json(); 
       if (jsonResponse.response === 'success') { 
        const userResponse: IUser = jsonResponse.user; 
        this._sessionService.setUserSession(userResponse); 
        this.loggedIn.next(true); 
        return true; 
       } else { 
        this._customFlashMessages.show('Got error login, please check your credentials and try again!'); 
        return false; 
       } 
      })); 
    } 
} 

accessGuard.service.ts

import {Injectable} from '@angular/core'; 
import {ActivatedRouteSnapshot, CanActivate, Router} from '@angular/router'; 
import {Observable} from 'rxjs/Observable'; 
import {AuthService} from './auth.service'; 
import {PopUpService} from './popup.service'; 

@Injectable() 
export class AccessGuard implements CanActivate { 
    loggedIn$: Observable<boolean>; 

    constructor(private authService: AuthService, private _popupService: PopUpService, private router: Router) { 
     this.loggedIn$ = this.authService.isLoggedIn; 
    } 

    canActivate(route: ActivatedRouteSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
     const requiresLogin = route.data.requiresLogin || false; 
     if (requiresLogin) { 
      this.authService.isLoggedIn.subscribe(// even tried with .map() 
       result => { 
        console.log(result); // Logs a promise object 
        if (!result) { 
         console.log("protected route"); // Never reached 
         // If not logged in shop popup and stay on that page 
         this._popupService.showPopUp(); 
         this._popupService.setCallbackRoute(route.url.join('/')); 
         return false; 
        } 
        console.log('logged in'); // Never reached 
        return true; 
       }); 
     } 
     return true; 
    } 
} 

我嘗試了幾件事情。我的代碼工作,如果我直接檢查sessionStorage('用戶'),但不能使用observable。

任何幫助表示讚賞。

謝謝!

+0

從你的解釋,彈出必須是不是後衛,但在網頁組件,在其內部可以實現'ngOnInit()'檢查,如果用戶'isSignedIn',如果不是,用登錄表單觸發彈出窗口。 Guard在返回false之前只能重定向到主頁。 – Vadim

回答

0

這是正確答案,問題出在訂閱方法裏面的邏輯裏。

這裏是正確的accesGuard.service.ts

@Injectable() 
export class AccessGuard implements CanActivate { 

    constructor(private authService: AuthService, private _popupService: PopUpService, private router: Router) { 
    } 

    canActivate(route: ActivatedRouteSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
     const requiresLogin = route.data.requiresLogin || false; 
     if (requiresLogin) { 
      this.authService.isLoggedIn.subscribe(
       result => { 
        if (!result) { 
         // If not logged in shop popup and stay on that page 
         this._popupService.showPopUp(); 
         this._popupService.setCallbackRoute(route.url.join('/')); 
         this.router.navigate(['/']); 
         return false; 
        } 
        return true; 
       }); 

      return true; 
     }else{ 

     return true; 
     } 
    } 
} 
+0

@Robin Dijkhof邏輯在canActivate方法中是允許的。通過這種方式,您可以對每個經過驗證的路線使用相同的過程。 – SBO

+0

允許邏輯,但顯示模型不僅僅是邏輯。你也確定這是工作。訂閱是異步的,所以這看起來很奇怪。我懷疑它永遠不會是假的。如果它有效,你是幸運的,但如果有一個小的延遲會發生什麼。 –

+0

嗯..它甚至可以在生產服務器上運行。你的意思是我應該返回this.authService.isLoggedIn.subscribe()結果,而不是在最後返回true嗎? – SBO

0

你需要返回一個observable。

canActivate(route: ActivatedRouteSnapshot): Observable<boolean> | Promise<boolean> | boolean { 
    const requiresLogin = route.data.requiresLogin || false; 
    if (requiresLogin) { 
     return this.authService.isLoggedIn; 
    } 
    return Observable.of(false); 
} 
+0

我怎樣才能顯示彈出窗口,並把登錄內每個私人頁面? – SBO

+0

我不認爲這是可能的從後衛。我認爲將重定向到專用的登錄頁面併發送請求將會更好。成功登錄後,您可以重新導向。 –

+0

我想做這樣的事情:https://stackoverflow.com/questions/39935721/how-to-return-observable-from-subscribe – SBO