0

我正在 Angular 中创建一个 Route Guard;它的运作方式取决于您是否与公司有关联;它会将您发送到特定组件。Unfourtnetly,当运行 canLoad 方法时,它不会保存 companylist 变量的值。任何帮助,将不胜感激!

import { Injectable } from '@angular/core';
import { CanActivate, Router, CanLoad } from '@angular/router';
import { AuthService } from 'src/app/auth.service';
import { User } from 'src/models/user';
import {ListdataService} from 'src/app/listdata.service';

@Injectable({
  providedIn: 'root'
})
export class CompanyonlyService implements CanActivate, CanLoad {
  companieslist=[];

  constructor(private authService: AuthService, private router: Router,private dataService:ListdataService) { }



  run(){
    this.dataService.sendGetRequestcompanies().subscribe((data: any[])=>{
      let tmp = [];

      for (let key in data)
        if (data.hasOwnProperty(key))
          tmp.push(data[key])

          this.companieslist = tmp;
          console.log(this.companieslist)





    }   )}



  canActivate() {
    return this.canLoad()
  }


    //this method won't set the value of the variable why?
    canLoad(){

      this.run()
      console.log('after loop')
      console.log(this.companieslist)
    if (this.companieslist.length==0) {

      this.router.navigate(['/companysignup']);

    }
    else{
      this.router.navigate(['/dashboard']);
    }

    return this.authService.isLoggedIn();
  } 
  }


[在此处输入图像描述]这是我在控制台中返回的内容

4

3 回答 3

1

由于请求,方法 run 是异步的,您没有检查请求是否已经完成。

因此,如果在检查条件时请求未完成,companyList 的大小将始终等于 0。

检查此如何检查所有 HTTP 获取请求是否已完成(已解决) - Angular 2

于 2020-06-04T01:11:16.750 回答
1

问题是基于异步的。run 方法运行一个影响 campaniesList 数组的订阅。但是当您调用 run 并触发订阅时,它不会停止执行您的代码。因此,当您在运行后立即登录时:

  this.run()
  console.log('after loop')
  console.log(this.companieslist)

它在嵌套在 subscribe 块中的内容之前运行:

 this.dataService.sendGetRequestcompanies().subscribe((data: any[])=>{
  let tmp = [];

  for (let key in data)
    if (data.hasOwnProperty(key))
      tmp.push(data[key])

      this.companieslist = tmp;
      console.log(this.companieslist)
}

编辑:

我已经到位的警卫示例

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
   return this.userService.getPermissions(this.userService.userId).pipe(map((permissions: string[]) => {
       if(permissions.length === 0) {
            this.router.navigateByUrl('/dashboard');
       }
       return permissions.length > 0; // this is where you could check for some specific permission maybe?
   }),
   retry(3),
   catchError(() => {
    this.router.navigateByUrl('/dashboard');
    return of(false);
   })
于 2020-06-04T01:12:40.220 回答
0

CanLoad 守卫的方法类型签名允许您返回一个Observable<boolean>、一个Promise<boolean>或只是一个普通的boolean

CanActivate 守卫是类似的,除了你可以返回一个booleanorUrlTree但仍然允许它是一个 Observable 或一个 Promise。这意味着该函数可以等待您的调用完成。

出于您的目的, CanActivate 就足够了,除非您想阻止客户端完全加载不同的路由模块,但这超出了此答案的范围。

您的 dataService 请求返回一个 Observable,因此您需要做的就是将请求返回的数据映射到 CanActivate 的正确返回类型。

这是您可以做到的一种方法:

import { Injectable } from '@angular/core';
import { CanActivate, Router, CanLoad } from '@angular/router';
import { map } from 'rxjs/operators';
import { AuthService } from 'src/app/auth.service';
import { User } from 'src/models/user';
import { ListdataService } from 'src/app/listdata.service';

@Injectable({
  providedIn: 'root'
})
export class CompanyonlyService implements CanActivate {

  constructor(private authService: AuthService, private router: Router,private dataService:ListdataService) { }

  canActivate() {
    return this.dataService.sendGetRequestcompanies().pipe(
      map((data: any[]) => {
        if(data && data.length > 0) return this.router.createUrlTree(['/dashboard']);
        else return this.router.createUrlTree(['/companysignup']);
      })
    );
  }

}

使用 Typescript 的主要优点之一是知道您的参数是什么类型或返回类型是什么。如果您没有正确声明它们,它无法拯救您自己,并且您错过了看到您可以返回的不同可能选项。

完全类型化的方法是:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean|UrlTree> | Promise<boolean|UrlTree> | boolean|UrlTree {
    return this.dataService.sendGetRequestcompanies().pipe(
      map((data: any[]) => {
        if(data && data.length > 0) return this.router.createUrlTree(['/dashboard']);
        else return this.router.createUrlTree(['/companysignup']);
      })
    );
  }
于 2020-06-04T03:06:53.367 回答