繁体   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