每次激活 RouteGuard 时重新加载 ngrx 状态数据
Reload ngrx state data every time RouteGuard is activated
对于实体的受保护视图,我使用 RouteGuard
将所需视图所需的数据预加载到 ngrx 存储中。但是,来自后端的相应数据会随时间变化。因此,每次路由被激活时,store 的旧状态应该被来自后端的新数据覆盖,如果有的话。只有当新数据已经加载到存储中并且完全可用时,路由才应该被激活。可能是后台删除了实体
为此,我有以下最小示例:Stackblitz Example
在当前的实现中,每次调用路由时都会调用操作 GetEntity()
,从后端加载数据。但是路由仍然是根据商店以前的状态激活的,这不是我们想要的行为。应该以某种方式使旧状态无效或删除,以便无法激活路由。
这是RouteGuard
的canActivate
函数的逻辑:
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),
);
}
因此两个问题:
- 如何更改RouteGuard,使其每次激活时从后端加载数据,只激活新加载数据的路由?
- RouteGuard 是否是实现这种从后端重新加载逻辑的正确位置,或者是否需要进一步调整状态或效果?
- 方法是在你的守卫启动时添加标志,数据应该被刷新,只有当它被刷新时才发出。
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),
);
}
- 正确的地方是解析器
@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
对于实体的受保护视图,我使用 RouteGuard
将所需视图所需的数据预加载到 ngrx 存储中。但是,来自后端的相应数据会随时间变化。因此,每次路由被激活时,store 的旧状态应该被来自后端的新数据覆盖,如果有的话。只有当新数据已经加载到存储中并且完全可用时,路由才应该被激活。可能是后台删除了实体
为此,我有以下最小示例:Stackblitz Example
在当前的实现中,每次调用路由时都会调用操作 GetEntity()
,从后端加载数据。但是路由仍然是根据商店以前的状态激活的,这不是我们想要的行为。应该以某种方式使旧状态无效或删除,以便无法激活路由。
这是RouteGuard
的canActivate
函数的逻辑:
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),
);
}
因此两个问题:
- 如何更改RouteGuard,使其每次激活时从后端加载数据,只激活新加载数据的路由?
- RouteGuard 是否是实现这种从后端重新加载逻辑的正确位置,或者是否需要进一步调整状态或效果?
- 方法是在你的守卫启动时添加标志,数据应该被刷新,只有当它被刷新时才发出。
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),
);
}
- 正确的地方是解析器
@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