Mar*_*nck 10 angular2-routing ngrx ngrx-effects angular
我是ngrx/store的初学者,这是我使用它的第一个项目.
我已经使用ngrx/store成功设置了我的角度项目,并且我可以在初始化主要组件后调度一个加载操作,如下所示:
ngOnInit() {
this.store.dispatch({type: LOAD_STATISTICS});
}
我已设置一个效果,以便在调度此操作时加载数据:
@Effect()
loadStatistik = this.actions.ofType(LOAD_STATISTICS).switchMap(() => {
return this.myService.loadStatistics().map(response => {
return {type: NEW_STATISTICS, payload: response};
});
});
Run Code Online (Sandbox Code Playgroud)
我的减速机看起来像这样:
reduce(oldstate: Statistics = initialStatistics, action: Action): Statistik {
switch (action.type) {
case LOAD_STATISTICS:
return oldstate;
case NEW_STATISTICS:
const newstate = new Statistics(action.payload);
return newstate;
....
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但我无法理解如何使用路由器防护,因为我目前只需要调度一次LOAD_ACTION.
此外,组件必须调度LOAD操作,加载初始数据对我来说听起来不对.我希望商店本身知道它需要加载数据,我不必先调度一个动作.如果是这种情况,我可以删除组件中的ngOnInit()方法.
我已经查看了ngrx-example-app,但我还没有真正了解它是如何工作的.
编辑:
添加一个返回ngrx-store observable的解析防护后,该路由不会被激活.这是决心:
@Injectable()
export class StatisticsResolver implements Resolve<Statistik> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Statistik> {
// return Observable.of(new Statistik());
return this.store.select("statistik").map(statistik => {
console.log("stats", statistik);
return statistik;
});
}
Run Code Online (Sandbox Code Playgroud)
这是路线:
const routes: Routes = [
{path: '', component: TelefonanlageComponent, resolve: {statistik: TelefonieStatistikResolver}},
];
Run Code Online (Sandbox Code Playgroud)
我不太明白为什么要通过解析器将已解析的数据发送到组件.设置ngrx存储的关键是拥有单一的数据源.所以,你想在这里做的是确保数据是真的.休息时,组件可以使用选择器从商店获取数据.
我可以看到你是LOAD_ACTION从ngOnInit组件的方法调用的.您无法调用操作来解析数据,然后该数据会导致Init您调用该操作的组件!这就是您的路由器未加载路由的原因.
不确定你是否明白这一点,但这是有道理的!
简单来说,你在做什么就是这个.您正在锁定房间,然后将钥匙推过门下方的缝隙,然后想知道为什么门没有打开.
随身携带钥匙!
守卫的解决方法应该调用LOAD_ACTION.然后解决方案应该等待数据加载,然后路由器应该继续到组件.
你是怎样做的?
其他答案是设置订阅,但问题是你不想在你的警卫中这样做.订阅警卫并不是一个好习惯,因为他们需要取消订阅,但如果数据没有得到解决,或者警卫返回错误,那么路由器永远不会取消订阅而且我们弄得一团糟.
所以,使用take(n).此运算符将从n订阅中获取值,然后自动终止订阅.
此外,在你的行动中,你需要LOAD_STATISTICS_SUCCESS和a LOAD_STATISTICS_FAIL.由于您的服务方法可能会失败!
在reducer中State,您需要一个loaded属性,该属性true在服务调用成功并调用LOAD_STATISTICS_SUCCESSaction 时转向.
在主减速器中添加一个选择器,getStatisticsLoaded然后在你的gaurd中,你的设置将如下所示:
resolve(): Observable<boolean> {
this.store.dispatch({type: LOAD_STATISTICS});
return this.store.select(getStatisticsLoaded)
.filter(loaded => loaded)
.take(1);
Run Code Online (Sandbox Code Playgroud)
}
因此,只有当loaded属性更改为true时,filter才会允许该流继续.take将取第一个值并传递.此时解析完成,路由器可以继续.
再次,take将杀死订阅.
在AngularFrance提供宝贵意见后,我自己解决了这个问题.由于我还是初学者,我不知道这是否应该如何完成,但它确实有效.
我像这样实现了一个CanActivate Guard:
@Injectable()
export class TelefonieStatistikGuard implements CanActivate {
constructor(private store: Store<AppState>) {}
waitForDataToLoad(): Observable<Statistik> {
return this.store.select(state => state.statistik)
.filter(statistik => statistik && !statistik.empty);
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
this.store.dispatch({type: LOAD_STATISTIK});
return this.waitForDataToLoad()
.switchMap(() => {
return Observable.of(true);
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
方法canActivate(...)首先调度一个动作来加载数据.在waitForDataToLoad()中,我们过滤数据已经存在但不为空(我的业务逻辑的实现细节).
返回true后,我们调用switchMap返回一个Observable为true.
| 归档时间: |
|
| 查看次数: |
6171 次 |
| 最近记录: |