关于观察者根据他们的回归合并的混淆

时间:2016-12-06 12:34:22

标签: angular typescript redux observable ngrx

我正在开发一个angular2应用程序,它使用ngrx存储方法来管理状态。应用程序是github上的开源here

问题陈述

我遇到的具体问题是当其他observable返回null 时,使用从一个observable发出的值。

当我的ngrx 商店 中存在数据时,我不想查询后端api。

Angular2代码

以下是我的trips.reducer.ts文件

export interface State {
  ids: string[];
  trips: { [id: string]: Trip };
  selectedTripId: string;
}

const initialState = {
  ids: [],
  trips: {},
  selectedTripId: null
}

export function reducer(state = initialState, action: Action ): State {}

export function getTrips(state : State) {
  return state.trips;
} 

export function getTripIds(state: State) {
  return state.ids;
}

export function getSelectedTripId(state: State) {
  return state.selectedTripId;
}

以下是我的基础缩减器index.ts

export interface State {
  trips: fromTripsReducer.State;    
} 

const reducers = {
  trips: fromTripsReducer.reducer,
}

export function getTripsState(state: State): fromTripsReducer.State {
  return state.trips;
}

export const getTrips = createSelector(getTripsState, fromTripsReducer.getTrips);
export const getTripIds = createSelector(getTripsState, fromTripsReducer.getTripIds);
export const getSelectedTripId = createSelector(getTripsState, fromTripsReducer.getSelectedTripId);
export const getSelectedCityId = createSelector(getTripsState, fromTripsReducer.getSelectedCityId);

export const getTripsCollection = createSelector(getTrips, getTripIds, (trips, ids) => {
  return ids.map(id => trips[id]);
});

export const getSelectedTrip = createSelector(getTrips, getSelectedTripId, (trips, id) => {
  return trips[id];
});

现在我可以在trip-detail.component.ts这样的

中获得特定的旅程
selectedTrip$: Trip;

constructor(private store: Store<fromRoot.State>) {
  this.selectedTrip$ = this.store.select(fromRoot.getSelectedTrip);
}

现在,如果我重新加载路由localhost:4200/trips/2,那么我们的商店将初始化为initialState,如下所示

const initialState = {
  ids: [],
  trips: {},
  selectedTripId: null
}

以下方法不能用作getTrips,getSelectedTripId将为null

export const getSelectedTrip = createSelector(getTrips, getSelectedTripId, (trips, id) => {
  return trips[id];
});

所以现在我可以制作一个后端请求,它只会加载基于url id的单行程,如下所示

return this.http.get(`${this.apiLink}/trips/${trip_id}.json`
  .map((data) => data.json())

但我想只在商店里没有旅行时才提出后端请求

this.selectedTrip $返回null或undefined。

this.selectedTrip$ = this.store.select(fromRoot.getSelectedTrip);

1 个答案:

答案 0 :(得分:0)

如果在显示组件之前需要准备好数据,则可以使用解析器。请参阅此答案here

在您的情况下,它将看起来如下所示,解析器只会确保在selectedTripnull时初始化数据加载。注意:由于我们无法在任何地方使用解析器的返回数据,我们只能返回任何内容。

@Injectable()
export class SelectedTripResolver implements Resolve {

constructor(
    private store: Store
) {}

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {

    // get the selectedTrip
    return this.store.select(fromRoot.getSelectedTrip)
        // check if data is ready. If not trigger loading actions
        .map( (selectedTrip) => {
            if (selectedTrip === null) {
                //trigger action for loading trips & selectedTrip
                this.store.dispatch(new LoadTripAction());
                this.store.dispatch(new LoadselectedTripAction());
                return false; // just return anything
            } else {
                return true; // just return anything
            }
        });

}

此处解析器将确保在selectedTrip数据未就绪时触发加载操作。

trip-detail.component中,您只需要等待有效数据。像这样:

constructor(private store: Store<fromRoot.State>) {
    this.selectedTrip$ = this.store.select(fromRoot.getSelectedTrip)
        .filter(selectedTrip => selectedTrip !== null);
}

希望这有意义并帮助你。