首页 > 解决方案 > 每次激活 RouteGuard 时重新加载 ngrx 状态数据

问题描述

对于实体的受保护视图,我使用 aRouteGuard将所需视图所需的数据预加载到 ngrx 存储中。但是,来自后端的相应数据可能会随时间而变化。因此,每次激活路由时,如果有来自后端的新数据,则应使用来自后端的新数据覆盖存储的旧状态。仅当新数据已加载到存储中并且完全可用时,才应激活该路由。同时,该实体可能已在后端被删除。

为此,我有以下最小示例:Stackblitz Example

在当前实现中,GetEntity()每次调用路由时都会调用动作,这会从后端加载数据。但是路由仍然是根据商店之前的状态激活的,这不是我们想要的行为。旧状态应该以某种方式无效或删除以无法激活路由。
下面是canActivate函数的逻辑RouteGuard

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.store.pipe(select(selectEntityMap)).pipe(
      map(taskMap => Object.keys(taskMap).length > 0),
      tap(loaded => {
        this.store.dispatch(GetEntity()); // trigger backend loading
      }),
      filter(loaded => !!loaded), // waiting until the enties has been loaded.
      take(1),
    );
  }

因此有两个问题:

  1. 如何更改 RouteGuard 以便每次激活时从后端加载数据,并且仅使用新加载的数据激活路由?
  2. RouteGuard 是实现从后端重新加载的逻辑的正确位置,还是需要进一步调整状态或效果?

标签: angulartypescriptangular2-routingngrxngrx-store

解决方案


  1. 方法是在您的警卫开始时添加标志,表明数据应该被刷新并仅在刷新时才发出。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    // it should reset `taskMap` to undefined.
    // initial value of taskMap has to be null (anything but not undefined).
    this.store.dispatch(GetEntity());

    return this.store.pipe(select(selectEntityMap)).pipe(
      skipWhile(taskMap => taskMap !== undefined), // waiting until start
      skipWhile(taskMap => taskMap === undefined), // waiting until end

      take(1),
      map(taskMap => taskMap !== null),
    );
  }
  1. 正确的地方是解析器
@Injectable({
providedIn: 'root'
})
export class UserResolverService implements Resolve<any> {
  constructor(private fakeApi: FakeApiService) { }
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.fakeApi.getUsers().pipe(
      catchError((error) => {
      return empty();
      });
    );
  }
}

您可以在此处阅读更多信息:https ://dzone.com/articles/understanding-angular-route-resolvers-by-example


推荐阅读