В моем основном компоненте я начинаю инициализацию своих данных:
_store.dispatch(_statusActions.initialize());
Это запускает все действия инициализации:
@Effect()
loading$ = this.actions$
.ofType(StatusActions.INITIALIZING)
.mergeMap(() => Observable.from([
this._characterActions.initCharacters(),
this._vehicleActions.initVehicles()
]))
После загрузки данных в Store для всех сущностей магазина срабатывают успешные действия.
Для автомобилей:
@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, я хочу, чтобы мое действие INITIALIZED было запущено для установки флага READY в моем хранилище.
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
Snks mtx, я следил за вашим первым и быстрее adwise.
Извините за лишний вопрос, но я действительно застрял в поисках хорошего способа сделать следующий шаг. Как удерживать эту подписку (внутри компонента) до тех пор, пока мое ИНИЦИАЛИЗИРОВАННОЕ действие не будет запущено (нужно удалить этот ужасный костыль с помощью if (cars.length> 0)):
constructor(
...
) {
this.vehicles$ = _store.select(s => s.vehicles);
this.initialized$ = _store.select(s => s.initilized);
}
ngOnInit() {
let id = this._route.snapshot.params.id ? this._route.snapshot.params.id :
null;
this.sub = this.vehicles$.subscribe(vehicles => {
if (vehicles.length > 0){
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;
}
})
}
ngOnDestroy(){
this.sub && this.sub.unsubscribe();
}
Я попытался вставить 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;
});
}
Чтобы воспроизвести мою проблему, просто нажмите на один из автомобилей в списке. Обратный вызов подписки не срабатывает. Затем нажмите F5 -> теперь машина загружается, обратный вызов маяка был запущен, как и было задумано.
Полный исходный код находится здесь: GitHub, последняя версия работает на страницах GitHub