Angular 如何捕获两个(或更多)@ngrx/store操作并在组件中保留订阅,直到发生这种情况?
在我的主组件中,我开始初始化我的数据:Angular 如何捕获两个(或更多)@ngrx/store操作并在组件中保留订阅,直到发生这种情况?,angular,ngrx,ngrx-effects,ngrx-store,Angular,Ngrx,Ngrx Effects,Ngrx Store,在我的主组件中,我开始初始化我的数据: _store.dispatch(_statusActions.initialize()); 这将触发所有初始化操作: @Effect() loading$ = this.actions$ .ofType(StatusActions.INITIALIZING) .mergeMap(() => Observable.from([ this._characterActions.initCharacters(),
_store.dispatch(_statusActions.initialize());
这将触发所有初始化操作:
@Effect()
loading$ = this.actions$
.ofType(StatusActions.INITIALIZING)
.mergeMap(() => Observable.from([
this._characterActions.initCharacters(),
this._vehicleActions.initVehicles()
]))
将数据加载到存储中后,将触发所有存储实体的成功操作
对于车辆:
@Effect()
loadVehicles$ = this.actions$
.ofType(VehicleActions.INIT_VEHICLES)
.switchMap(() => this._vehicleService.getVehicles()
.map((vehicles: Vehicle[]) => this._vehicleActions.initVehiclesSuccess(vehicles))
.catch(err => Observable.of(this._statusActions.dataLoadingError('vehicles')))
);
对于角色:
@Effect()
loadVehicles$ = this.actions$
.ofType(CharacterActions.INIT_CHARACTERS)
.switchMap(() => this._characterService.getCharacters())
.map((characters: Character[]) =>
this._characterActions.initCharactersSucess(characters))
最后,在触发所有*_DATA_SUCCESS操作之后,我希望触发初始化的操作以将就绪标志放入存储中
export const initReducer = (state: boolean = false, action: Action): boolean => {
switch (action.type){
case StatusActions.INITIALIZING:
return false;
case StatusActions.INITIALIZED:
console.log('App initialized...');
return true;
default:
return state;
}
我的问题是——如何做到这一点?如何知道何时触发了所有成功操作
UPD
Snksmtx,我跟随你的第一个更快的adwise
很抱歉有额外的问题,但我真的一直在寻找好的方法来做这个
下一步。如何保持此订阅(组件内部),直到触发我的初始化操作(需要使用if(vehicles.length>0)移除此可怕的拐杖):
我试图在subscribe()之前插入skipUntil(),但现在遇到了问题
从另一个组件打开此组件(当所有数据都已加载时)。在这种情况下,无法再触发订阅回调!我无法理解为什么
...
private initDone$ = new Subject<boolean>();
...
this.initialized$.subscribe((init: Init) => {
if(init.app)
this.initDone$.next(true);
})
this.sub = this.vehicles$.skipUntil(this.initDone$).subscribe(vehicles => {
if(id)
this.vehicle = vehicles.find(item => item.id === Number(id))
else
this.vehicle = new Vehicle(vehicles[vehicles.length-1].id+1, '');
this.viewReady = true;
});
}
。。。
private initDone$=新主题();
...
此.initialized$.subscribe((init:init)=>{
if(init.app)
this.initDone$.next(true);
})
this.sub=this.vehicles$.skipUntil(this.initDone$).subscribe(vehicles=>{
如果(id)
this.vehicle=vehicles.find(item=>item.id==Number(id))
其他的
this.vehicle=新车(车辆[vehicles.length-1].id+1');
this.viewReady=true;
});
}
要重现我的问题,只需按下列表中的一辆车。没有开火。然后按F5->now vehicle loading,beacouse回调按设计启动
完整的源代码如下:,
上次运行的版本我可以想出两种方法来实现这一点(我确信还有其他方法): 1.在减速器中 通过减少
initReducer
中的两个*\u DATA\u SUCCESS操作,让initReducer
状态为每个必须成功的请求设置标志,以便将就绪标志设置为true
:
init.reducer.ts
导出接口初始状态={
characterSuccess:boolean,
车辆成功:布尔值,
就绪:布尔值
}
常量初始状态={
characterSuccess=false,
vehicleSuccess=错误,
就绪=错误
};
export const initReducer(state:InitState=initialState,action:action):InitState{
开关(动作类型){
/* ...
*其他情况,如初始化或初始化错误。。。
*/
case CharacterActions.CHARACTER\u数据\u成功:{
/*将characterSuccess设置为true。
*
*如果VehicleSucces已为true
*这意味着两个请求都已成功完成
*否则ready将保持false,直到第二个请求完成
*/
返回Object.assign({},state{
人物成功:真的
就绪:state.vehiclesucces
});
}
案例VehicleActions.VEHICLE\u数据\u成功:{
/*将VehicleSucces设置为true。
*
*如果characterSuccess已经为true
*这意味着两个请求都已成功完成
*否则ready将保持false,直到第二个请求完成
*/
返回Object.assign({},state{
车辆成功:对,
准备就绪:state.characterSuccess
});
}
违约:
返回状态;
}
}
2.使用选择器
如果创建initReducer
只是为了跟踪当前是否正在初始化,则可以忽略整个reducer,而使用计算派生状态的选择器。我喜欢使用库,因为它可以让您创建高效的选择器,只有在发生更改时才会重新计算(=记忆选择器) 首先,将
加载
-和就绪
-标志添加到车辆和字符减速器的状态形状中。然后,在减速器级别添加选择器功能。
车辆减速器示例: 车辆.减速器.ts (对字符缩减器重复相同的操作)
导出接口车辆状态{
//车辆ID和实体等。。。
加载:布尔;
就绪:布尔;
}
常量初始状态:车辆状态={
//其他初始值
加载:false,
就绪:错误
}
导出功能减速器(状态=初始状态,操作:操作):车辆状态{
开关(动作类型){
//其他情况。。。
case VehicleActions.INIT_车辆:{
返回Object.assign({},state{
加载:对,
就绪:错误
});
}
案例VehicleActions.VEHICLE\u数据\u成功:{
返回Object.assign({},state{
/*其他还原逻辑,如
*实体:action.payload
*/
加载:false,
准备好了吗
});
}
违约:
返回状态;
}
}
//选择器功能
export const getLoading=(状态:VehicleState)=>state.loading;
export const getReady=(状态:VehicleState)=>state.ready;
接下来,在根减缩器或放置选择器的附加文件中,组合选择器,以获得所需的派生状态:
选择器。ts
从“/root.reducer”导入{MyGlobalAppState};
从“/vehicle.reducer”导入*作为车辆;
从“/character.reducer”导入*作为fromCharacter;
从“重新选择”导入{createSelector};
//车辆状态选择器
export const getVehicleState=(状态:MyGlobalAppState)=>state.vehicle;
//字符状态选择器
导出常量getCharacterState=(状态:MyGlobalAppState)=>state.charact
...
private initDone$ = new Subject<boolean>();
...
this.initialized$.subscribe((init: Init) => {
if(init.app)
this.initDone$.next(true);
})
this.sub = this.vehicles$.skipUntil(this.initDone$).subscribe(vehicles => {
if(id)
this.vehicle = vehicles.find(item => item.id === Number(id))
else
this.vehicle = new Vehicle(vehicles[vehicles.length-1].id+1, '');
this.viewReady = true;
});
}