【问题标题】:Pass data to angular Guard CanActivateChild将数据传递给 Angular Guard CanActivateChild
【发布时间】:2021-08-18 21:03:10
【问题描述】:

我实际上有多个守卫,它们共享从我的 API 调用的完全相同的数据。

我的守卫是这样的:

export class GuardBlockAgent implements CanActivateChild {
 ...

 canActivateChild(
        route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
    ): Observable<boolean> | boolean {

        return this.userService.retrieveMyUser(null, environment.liveMode).map(
        ...
    )}

我正在寻找一种方法来在我的警卫之间共享我的数据。而不是多次调用相同的数据。

this post 中,他们将这种方式与canActivate 一起使用

{ 
  path: 'super-user-stuff', 
  component: SuperUserStuffComponent,
  canActivate: RoleGuard,
  data: {roles: ['SuperAdmin', ...]}
}

但是如何传递来自我的 API 的动态数据?

theme-routing.module.ts

const routes: Routes = [
    {
        "path": "",
        "component": ThemeComponent,
        "resolve": { me: AgentResolver },
        "canActivate": [AuthGuard],
        "children": [
            {
                "path": "...",
                "loadChildren": "...",
                "canActivateChild": [GuardBlockAgent]
            },
];

@NgModule({
    imports: [RouterModule.forChild(routes)],
    exports: [RouterModule]
})
export class ThemeRoutingModule { }

编辑:localStroage 不安全,这就是我不想使用它的原因。

【问题讨论】:

  • 在警卫中使用constructor 并注入一些状态服务有什么问题?
  • 加载时间,越来越长了。我宁愿打一次电话而不是 X 次电话
  • 你可以为userService创建一个根级的facade服务。它应该缓存用户和任何其他关系数据。
  • 有什么例子吗?没听说过
  • @crg 我发布了一个答案并为您创建了一个 stackBlitz 示例。

标签: javascript angular


【解决方案1】:

您可以为您的UserService 创建一个外观层。该层存储您的用户以供运行时使用,如果数据存在,它不会向服务器发送请求。

查看stackBlitz 示例。 (检查控制台)

创建它;

第 1 步:创建外观服务。

user-service.facade.ts

@Injectable({
  providedIn: 'root'
})
export class UserServiceFacade extends UserService {
  private readonly user$ = new BehaviorSubject<{ name: string } | null>(null);

  retrieveMyUser(): Observable<{ name: string }> {
    return this.user$.pipe(
      startWith(this.user$.value),
      switchMap(user => (user ? of(user) : this.getUserFromServer())),
      take(1)
    );
  }

  private getUserFromServer() {
    return super.retrieveMyUser().pipe(tap(user => this.storeUser(user)));
  }

  private storeUser(user: { name: string }): void {
    this.user$.next(user);
  }
}

第 2 步: 覆盖 UserService 令牌的依赖注入。

app.module.ts 或您提供的任何位置 UserService

  providers: [
    {
      provide: UserService,
      useClass: UserServiceFacade
    }
  ],

它已经完成了!

【讨论】:

  • 感谢您的回答。我看不出它如何帮助我在警卫之间共享数据。可能我没看懂你是怎么用的。如果你能告诉我它在警卫中是如何工作的,那就太好了。我已经完成了你在 stackBlitz 中所做的事情,但它并没有改变任何东西......使用我的警卫时我仍然有多个调用
  • 实际上,在您的 stackBlitz 示例中,不需要 UserServiceFacade 来使其工作。看来你整个 UserServiceFacade 都没用了……
  • 如果用户已经存在,它正在存储数据而不是发送请求。这意味着您可以在任何地方调用retrieveMyUser 方法。如果用户存在,则立即返回用户,如果不存在,则发送请求并存储用户数据。在stackblitz 示例中,您可以检查控制台。它在发送检索用户的请求时正在记录。 @crg 此外,如果您需要更复杂的解决方案,您可以查看 state management 库,如 ngrx 或 ngxs 等。
  • 好像我做错了什么,它工作正常。当我进入新页面并呼叫警卫时,它不会再次拨打电话。再次感谢您的帮助!
猜你喜欢
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多