【发布时间】:2018-04-22 12:17:12
【问题描述】:
有一个简单的(Angular 4)路由守卫,它等待从后端加载一些数据:
@Injectable()
export class ContractsLoadedGuard implements CanActivate {
constructor(private store: Store<State>) { }
waitForData(): Observable<boolean> {
return this.store.select(state => state.contracts)
.map(contractList => !!contractList)
.filter(loaded => loaded)
.take(1);
}
canActivate(): Observable<boolean> { return this.waitForData(); }
}
路由:
const routes: Routes = [
{ path: 'app-list', canActivate: [ContractsLoadedGuard], component: AppListComponent },
];
最后还有一个由@ngrx/router-store v4 ROUTER_NAVIGATION action 触发的@ngrx/effects:
@Effect() routeChange$ = this.actions$
.ofType(ROUTER_NAVIGATION)
.filter((action: RouterNavigationAction) => action.payload.routerState.url.indexOf('/app-list') > -1)
.withLatestFrom(this.store.select(state => state.contracts))
.switchMap(([action, contracts]: ([RouterNavigationAction, ContractList])) =>
this.restClient.load(action.payload.routerState.queryParams, contract));
不幸的是,当导航更改为/app-list 时,ngrx 效果首先执行(在保护之前),因此数据state.contracts 尚不可用。 守卫还没有被处决。
我必须添加.combineLatest() Rx 操作员来等待contracts 数据也生效(这是警卫的工作):
@Effect() routeChange$ = this.actions$
.ofType(ROUTER_NAVIGATION)
.filter((action: RouterNavigationAction) => action.payload.routerState.url.indexOf('/app-list') > -1)
.combineLatest(this.contractListGuard.waitForContractsToLoad(), a => a) <- HERE
.withLatestFrom(this.store.select(state => state.contracts))
.switchMap(/* same here */)
我不确定这是否足够好的解决方案。必须有更好的方法来做到这一点 - 不要复制有效的保护功能。
总结一下:在应用程序 boostrap 上,我需要从后端获取一些数据 - contracts。如果用户导航到/app-list(立即重定向),则会从服务器获取其他数据-基于一些查询参数和contracts-ngrx 路由器ROUTER_NAVIGATIONeffect 执行顺序在警卫执行顺序之前。如何正确处理?
【问题讨论】:
标签: typescript ngrx ngrx-effects ngrx-store-4.0