簡體   English   中英

Angular - 如何使 canActivate 等待 promise 響應?

[英]Angular - How to make canActivate to await for promise response?

如果用戶已登錄,我會嘗試簽入 CanActivate gurad。
如果是,那么我將他導航到某個頁面。
如果沒有,那么我將他導航到登錄頁面。
我使用 promise。

我有一個名為LoginService的服務:

export class LoginService {

  urlcheck = 'http://localhost:80/isconnected.php';
  resultCheck;

  constructor(private http: HttpClient, private router: Router)
  {
  }

  async checkLogin()
  {
    const x = await this.updateConnectedState();
    return x;
  }

  updateConnectedState()
  {
    //formData here...
    return this.http.post(this.urlcheck, formData).toPromise()
      .then(
        (response) =>
        {
          this.resultCheck = response; 
          console.log(response);
          return this.resultCheck.state; //state is true/false
        },
        (error) => 
        { 
            console.log(error); 
            return false;  
        }
      );
    }
  }


canActivate Gurad:

export class BackHomeGuardService implements CanActivate
{
  constructor(private logService: LoginService, private router: Router)
  {
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean
  {
    const result = this.logService.checkLogin();
    console.log( result);

    if (result)
    {
      console.log('true');
      // navigate to hom page
      return true;
    }
    else
    {
      console.log('false');
      // navigate to login page
      return false;
    }
  }
}

守衛可以激活 function 總是返回 true。
我檢查了控制台,promise 結果是:

__zone_symbol__state: null
__zone_symbol__value: []

我想讓 canActive 在它做某事之前等待結果。
如果我的后端(php 代碼文件)需要 30 秒才能完成怎么辦?
我需要一個解決方案。 謝謝。

根據CanActivate的類型:

export declare interface CanActivate {
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
}

方法canActivate可以返回 Observable,Promise 或 boolean。

您可以簡單地返回您的checkLogin()調用,例如:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean {
    return this.logService.checkLogin();
}

一切都會奏效。


更新

從評論中回答問題“我如何處理我的 canActivate 中返回的 boolean”

CanActivate 的想法是由於某種條件限制對某些路由的訪問。 可以通過鏈接 Promise 或 Observable 來執行一些副作用(但我不確定它們將如何顯示,除非它是 console.log):

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean {
    return this.logService
      .checkLogin()
      .then(canLogin => {
         console.log('Can user login:', canLogin);
         // perform you side effects here
      })

}

如果查看 canActivate 方法的返回類型:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree

}

它可以返回一個簡單的 boolean 或 Promise 或 Observable。 另外,我認為您不需要在 LoginService 中將 Observable 轉換為 Promise。

canActivate 可以與 observable 一起使用,因此您可以 map 查詢結果以這種方式返回 observable

import { of, Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

export class LoginService {

  urlcheck = 'http://localhost:80/isconnected.php';
  resultCheck;

  constructor(private http: HttpClient, private router: Router) {
  }

  checkLogin(): Observable<boolean> {

    //formData here...
    return this.http.post(this.urlcheck, formData).pipe(
      map(
        (response) => {
          this.resultCheck = response;
          console.log(response);
          return this.resultCheck.state; //state is true/false
        }),
        catchError(error => {
          console.log(error);
          return of(false);
        })
      );
  }
}

export class BackHomeGuardService implements CanActivate
{
  constructor(private logService: LoginService, private router: Router)
  {
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>
  {
    return this.logService.checkLogin();
  }
}

canActivate可以具有以下返回類型: booleanPromise<boolean>Observable<boolean>

由於您已經有checkLogin()返回一個Promise ,它將解析為true/false 讓我們堅持使用PromiseObservable 正如其他人已經回答的那樣,您絕對可以返回this.logService.checkLogin()

   canActivate(): Promise<boolean> {
      return this.logService.checkLogin();
   }

現在,我看到您還想根據checkLogin()值導航到其他地方。 我建議將Promise轉換為Observable ,以便您可以利用tap運算符。 你可以這樣做:

   return fromPromise(this.logService.checkLogin()).pipe(
      tap(isLogin => {
         if (!isLogin) {
            // not login. navigate to login page
         }
      })
   )

我們真的不想在true的某個地方導航,因為當它為 true 時,Guard 會將用戶導航到被保護的路線。

暫無
暫無

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

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