Angular 中 canactivate 方法中的 API 调用

hel*_*rld 8 angular

我在 Angular 中使用canActivateusing guards。我想检查用户是否经过身份验证并根据结果保护路线。有两种类型的用户:Type1Type2,因此用户可以通过Type1Type2或进行身份验证unauthenticated。以下guard内容供Type1用户使用。

这是我的代码:

constructor(private authservice: AuthService, private router: Router, private route: ActivatedRoute){}
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean{

        const self = this;
        const expectedType = "type1";

        this.authservice.isUserAuthenticatedbyType(expectedType).then(
            function(data){
                if(data === false){
                    console.log(data);
                    self.router.navigate(['/'], {relativeTo: self.route});
                }
                return data;
            },
            function(error){
                self.router.navigate(['/']);
                return false;
            }
        );
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

问题是我进行了 API 调用以验证用户是否已通过身份验证并return false;在 API 结果之前执行。所以,暂时我看到一个不同的页面,然后它被路由到正确的页面。我该如何解决这个问题,我不想在 API 调用之前返回 false 或 true,但不这样做会导致错误。

我还尝试了以下方法:

return this.authservice.isUserAuthenticatedbyType(expectedType)
Run Code Online (Sandbox Code Playgroud)

但这只是将我导航到用户的http://localhost:4200url unauthenticated

我有以下路线:

{ path: "", component: HomeComponent },
Run Code Online (Sandbox Code Playgroud)

所以,在上面的场景中,HomeComponent应该被调用,但是ngOnInitHomeComponent 没有被调用。

Adr*_*rma 7

你也可以这样尝试:

canActivate(): Observable<boolean> | Promise<boolean> | boolean {
    return new Promise(res => {
        this.authservice.isUserAuthenticatedbyType("type1").subscribe(
            (data) => {
                if (data === true) {
                    res(true);
                } else {
                    this.router.navigate(['/']);
                    res(false);
                }
            },
            (error) => {
                this.router.navigate(['/']);
                res(false);
            }
        );
    });
}
Run Code Online (Sandbox Code Playgroud)


Ing*_*ürk 6

你可以这样实现:

角度 <= 7.0.0

public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  return this.authservice.isUserAuthenticatedbyType("type1").pipe(
    map(data => {
      if (data === false) {
        this.router.navigate(['/']);
        return false;
      }

      return !!data;
    }),
    catchError(() => {
      this.router.navigate(['/']);
      return of(false);
    }),
  );
}
Run Code Online (Sandbox Code Playgroud)

角度 >= 7.1.0

从 Angular 7.1.0 开始(请注意,它不在7.0.x 中),您也可以改为这样做,如果您有多个守卫,它会更短且更可预测:

public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  return this.authservice.isUserAuthenticatedbyType("type1").pipe(
    map(data => data === false ? this.router.parseUrl("/") : !!data)
    catchError(() => this.router.parseUrl("/")),
  );
}
Run Code Online (Sandbox Code Playgroud)


Rah*_*hul 5

如果您正在使用promise类似这样的尝试 - 主要想法是保持您的路由直到您的Api通话完成 - 我遇到了同样的问题,我已经通过返回Promise<boolean> 我的route护卫来实现它

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean{
    const self = this;
    const expectedType = "type1";
    retrun new Promise(res => {
      this.authservice.isUserAuthenticatedbyType(expectedType).then(
        function (data) {
          if (data === false) {
            console.log(data);
            self.router.navigate(['/'], { relativeTo: self.route });
          }
          res(data);
        },
        function (error) {
          self.router.navigate(['/']);
          res(false);
        }
      );
    });
  }
Run Code Online (Sandbox Code Playgroud)

这种方法解决了我的问题 - 它一直等到API返回数据并为路线指明方向

希望它会起作用 - 快乐编码!!