要在加载实际组件之前将数据从后端加载到我的ngrx存储中,我在路由的canActivate
属性中使用了路由保护。
{path: 'my-route', component: MyRouteComponent, canActivate: [LoadDataGuardService]}
警卫队应在商店中检查相应的数据是否已经可用。如果没有,则应将其从后端加载到商店中。一旦数据存储在商店中,就应该打开路线(首先单击并单击)。这是我的Guard的canActivate
方法。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const loadedTasks = this.store.pipe(select(selectTaskMap))
.pipe(map(taskMap => Object.keys(taskMap).length > 0));
loadedTasks
.pipe(
take(1),
filter(loaded => !loaded),
map(() => this.store.dispatch(GetTasks())))
.subscribe(() => this.store);
return loadedTasks
.pipe(take(1));
}
首先将数据加载到存储中就可以了。但是,如果必须加载数据,则必须再次单击链接以导航到所需的视图。似乎第一次单击仅加载了数据,但在成功加载数据后没有返回Observable的True
。
我如何调整代码以将数据加载到商店中,并在第一次单击时将数据加载到商店中后立即打开路线?
编辑:
这里是关于堆叠闪电战的再现实例:Stackblitz Link您可以清楚地看到,第二次单击Activate Route
链接后,才显示路线组件的内容。为了在测试时清除商店,我添加了一个按钮。
看起来好像是第一次尚未加载任务。
尝试在first
之后移动filter
。
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {Store, select } from '@ngrx/store';
import {filter, tap, map, take} from 'rxjs/operators';
import { selectEntityMap } from './store/selectors/entity.selectors';
import { AppState } from './store/state/app.state';
import { GetEntity } from './store/actions/entity.actions';
@Injectable({
providedIn: 'root'
})
export class LoadDataGuardService implements CanActivate {
constructor(public router: Router, private store: Store<AppState>) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.store.pipe(select(selectEntityMap)).pipe(
map(taskMap => Object.keys(taskMap).length > 0),
tap(loaded => {
if (!loaded) { // checking if we need to dispatch the action.
this.store.dispatch(GetEntity());
}
}),
filter(loaded => !!loaded), // waiting until the tasks have been loaded.
take(1),
);
}
}