如何使 ngrx-store 与 canLoad 守卫一起工作
how to make ngrx-store working with canLoad guard
不过我不知道这是否是个好习惯。但下面是我正在尝试做的事情:
我有 2 个惰性加载模块:ManagementModule
和 ConfigurationModule
,路由配置如下:
const routes: Routes = [
{path: '', redirectTo: 'management', pathMatch: 'full'}, {
path: 'configuration',
loadChildren: './configuration/configuration.module#ConfigurationModule',
canLoad: [UnconfiguredGuard]
},
{
path: 'management',
loadChildren: './management/management.module#ManagementModule',
canLoad: [ConfiguredGuard]
}
]
基本上这个想法是检查系统状态并重定向到不同的阶段,例如。如果 sys 还没有配置,重定向到 /configuration
,否则,重定向到 /management
.
在我把@ngrx/store
加入项目之前,两个canLoad
守卫很简单:
// ConfiguredGuard:
canLoad(route) {
return this.configService.isConfigured()
.do((configured: boolean) => {
if (!configured) {
// redirect to /configuration if unconfigured
this.router.navigate(['/configuration']);
}
})
}
现在我要采用所有@ngrx/{store,effects,router-store} libs,然后上面的guard改成:
canLoad(route) {
this.store.dispatch(new CheckInitStatus());
return this.store.select('initStatus')
.filter(s => s.checked) // check only when loaded
.map(s => s.status === 'initialized')
.catch(() => of(false));
}
当然,副作用是这样定义的:
@Effect()
check$: Observable<InitStatusAction> = this.actions$
.ofType<CheckInitStatus>(CHECK_INITSTATUS)
.mergeMap(() => this.fetchInitStatus())
.map(status => new InitStatusChecked({status, checked: true}))
.catch(e => of(new InitStatusCheckFailure(e)));
但是导航没有发生,没有发出 ROUTER_NAVIGATION
动作。我在这里错过了什么吗?而且我想知道这是否是一个好习惯?我确实找到了一些 canActivate
守卫用法的例子,但是 none 用于 canLoad
守卫。请帮忙,谢谢!
调试了一天终于搞定了!修复很简单,在filter()
之后的操作链中添加first()
或take(1)
,我无法表达我现在的感受......但我确实意识到我需要一种心态更改以正确使用 RxJS。
canLoad(route) {
this.store.dispatch(new CheckInitStatus());
return this.store.select('initStatus')
.filter(s => s.checked) // check only when loaded
.first() // or equivalently take(1)
.map(s => s.status === 'initialized')
.catch(() => of(false));
}
我应该仔细阅读canActivate
的示例,这个take(1)/first()
运算符就在那里,例如:https://toddmotto.com/preloading-ngrx-store-route-guards
不过我不知道这是否是个好习惯。但下面是我正在尝试做的事情:
我有 2 个惰性加载模块:ManagementModule
和 ConfigurationModule
,路由配置如下:
const routes: Routes = [
{path: '', redirectTo: 'management', pathMatch: 'full'}, {
path: 'configuration',
loadChildren: './configuration/configuration.module#ConfigurationModule',
canLoad: [UnconfiguredGuard]
},
{
path: 'management',
loadChildren: './management/management.module#ManagementModule',
canLoad: [ConfiguredGuard]
}
]
基本上这个想法是检查系统状态并重定向到不同的阶段,例如。如果 sys 还没有配置,重定向到 /configuration
,否则,重定向到 /management
.
在我把@ngrx/store
加入项目之前,两个canLoad
守卫很简单:
// ConfiguredGuard:
canLoad(route) {
return this.configService.isConfigured()
.do((configured: boolean) => {
if (!configured) {
// redirect to /configuration if unconfigured
this.router.navigate(['/configuration']);
}
})
}
现在我要采用所有@ngrx/{store,effects,router-store} libs,然后上面的guard改成:
canLoad(route) {
this.store.dispatch(new CheckInitStatus());
return this.store.select('initStatus')
.filter(s => s.checked) // check only when loaded
.map(s => s.status === 'initialized')
.catch(() => of(false));
}
当然,副作用是这样定义的:
@Effect()
check$: Observable<InitStatusAction> = this.actions$
.ofType<CheckInitStatus>(CHECK_INITSTATUS)
.mergeMap(() => this.fetchInitStatus())
.map(status => new InitStatusChecked({status, checked: true}))
.catch(e => of(new InitStatusCheckFailure(e)));
但是导航没有发生,没有发出 ROUTER_NAVIGATION
动作。我在这里错过了什么吗?而且我想知道这是否是一个好习惯?我确实找到了一些 canActivate
守卫用法的例子,但是 none 用于 canLoad
守卫。请帮忙,谢谢!
调试了一天终于搞定了!修复很简单,在filter()
之后的操作链中添加first()
或take(1)
,我无法表达我现在的感受......但我确实意识到我需要一种心态更改以正确使用 RxJS。
canLoad(route) {
this.store.dispatch(new CheckInitStatus());
return this.store.select('initStatus')
.filter(s => s.checked) // check only when loaded
.first() // or equivalently take(1)
.map(s => s.status === 'initialized')
.catch(() => of(false));
}
我应该仔细阅读canActivate
的示例,这个take(1)/first()
运算符就在那里,例如:https://toddmotto.com/preloading-ngrx-store-route-guards