Angular 2. Guard取决于来自服务器

时间:2017-07-13 10:42:30

标签: angular

我有单身人士服务:

export class CarService {
  public currentCar: BehaviorSubject<Car> = new BehaviorSubject(null); 
  constructor(private jsonApiService: JsonApiService) {

      this.jsonApiService.get(`.../activeCar`);
        .subscribe(data => {
          if(data) {
              this.setActiveCar(data);
          }
        })
    }
  }

  public setActiveCar(activeCar: Car): void {
    this.currentBrokerageAccount.next(activeCar);
  }
}

然后,我在守卫中使用currentCar

canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (!this.canActivate()) {
      return false;
    }
    if (!this.carService.currentCar.getValue() && state.url !== '/settings') {
      this.router.navigate(['/settings']);
    }

    return true;
}

警卫检查当前车辆,如果有数据则允许打开页面,否则重定向到用户必须选择车辆的设置页面。所以,问题是当我在应用程序中使用菜单然后一切正常,但是当我第一次打开页面(或F5)时,我总是被重定向到设置页面。我理解原因:它是因为carService尚未从服务器获得活动汽车而且currentCar为空。如何妥善解决?

PS。流程如下:验证后,如果选择了汽车,用户将看到应用程序中的所有功能。但是,如果未选择汽车,则只有一个网址可用,而且它是settings。因此,如果未选择汽车,我会将用户重定向到设置页面。

2 个答案:

答案 0 :(得分:2)

您正在请求价值的行为主体可能仍在评估来自服务器的所选汽车。您可以使用获取值然后完成的AsyncSubject,而不是&#34;请求&#34;来自服务的当前价值,您应该订阅主题并让他将价值推给您。

//in your service
currentCar$ : AsyncSubject<Car> = new AsyncSubject();
this.jsonApiService.get(`.../activeCar`).subscribe(
    (car) => {
         currentCar$.next(car);
         currentCar$.complete(car);
    }
);

//in your guard
//instead of getValue() subscribe to the AsyncSubject
//you should probably handle the "null" case too
this.carService.currentCar$.subscribe(
     (car) => {
         if ( !car && state.url !== '/settings' ){
             this.router.navigate(['/settings']);
         }
     }
);

订阅将在AsyncSubject完成之前收到它发出的值。

答案 1 :(得分:0)

尝试这种方法

export class CarService {

  private data: any;

  constructor(private jsonApiService: JsonApiService) {
    }
    getCar(): Observable<any> {
      return this.jsonApiService.get('url')
        .map((response: Response) => {
          this.data = response.json().data;
            return this.data;
          }
        );
    }

    hasCarData() {
      return data ? true : false;
    }
  }

  public setActiveCar(activeCar: Car): void {
    this.currentBrokerageAccount.next(activeCar);
  }
}

canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (!this.canActivate()) {
      return false;
    }

    if(state.url !== '/settings') {
      this.carService.getCar()
      .subscribe((data: any) => {
        if (!this.carService.hasCarData()) {
          this.router.navigate(['/settings']);  
        } else {
          return true;
        }
      });
    } else {
      return true;
    }
}