簡體   English   中英

如何在 2 個 HTTP 請求將值返回到商店后觸發和 NgRx 操作

[英]How to trigger and NgRx action after 2 HTTP requests return values to the store

我在 2 個不同的數據庫中存儲了等效的數據類型。

  • SQL 數據庫中,我存儲了所有食物的大量列表。
  • Mongo 數據庫中,我正在存儲個人的食物數據,該數據將覆蓋提供的默認食物數據。

這兩種類型的數據都存儲在我的ngrx store ApplicationState

export interface ApplicationState {
   serverFoodData: FoodData;
   userFoodData: FoodData;
   mergedFoodData: FoodData;
}

我需要保留其中每一個的版本,以便在用戶添加它們時我可以保存額外的userFoodData覆蓋,這樣我就可以在發生這種情況時重新計算mergedFoodData

因此,我需要檢測兩個http請求何時都已被解析到商店並觸發操作以計算新的mergedFoodData對象。 我怎樣才能做到這一點?

目前我正在dispatch() ing 和 action 從app.component.ts加載每個

  constructor(private store: Store<ApplicationState>) {

    this.store.dispatch(new LoadFoodsAction());
    this.store.dispatch(new LoadUserDataAction(1)); // 1 = temporary userID
    // this.foodStates$ = store.select(foodStatesSelector);
    // this.foodStates$.subscribe(foodStates => this.currentFoodStates = foodStates);
    // this.store.dispatch(new BuildMergedFoodDataAction(this.currentFoodStates))
  }

正如您所看到的,我試圖調度一個操作來合並 2 個FoodData對象,但它是dispatch()與未實現的值,因為http調用尚未響應。

動作.ts

// SQL FOODS
export const FOODS_LOADED_ACTION = 'FOODS_LOADED_ACTION';
export const LOAD_FOODS_ACTION = 'LOAD_FOODS_ACTION';


export class FoodsLoadedAction implements Action {
    readonly type = FOODS_LOADED_ACTION;
    constructor(public payload?: AllFoodData) { } // '?' is important
}
export class LoadFoodsAction implements Action {
    readonly type = LOAD_FOODS_ACTION;
    constructor(public payload: number) { }
}


// USER FOODS ACTIONS
export const LOAD_USER_DATA_ACTION = 'LOAD_USER_DATA_ACTION';
export const USER_DATA_LOADED_ACTION = 'USER_DATA_LOADED_ACTION';

export class UserDataLoadedAction implements Action {
    readonly type = USER_DATA_LOADED_ACTION;
    constructor(public payload?: AllUserData) { }
}
export class LoadUserDataAction implements Action {
    readonly type = LOAD_USER_DATA_ACTION;
    constructor(public payload: number) { }
}

// MERGE FOODS ACTION
export const BUILD_MERGED_FOOD_DATA_ACTION = 'BUILD_MERGED_FOOD_DATA_ACTION';

export class BuildMergedFoodDataAction implements Action {
    readonly type = BUILD_MERGED_FOOD_DATA_ACTION;
    constructor(public payload: FoodStates) { }
}

LoadFoodsEffectService.ts監聽來自app.component.tsdispatch並調用http服務

@Injectable()
export class LoadFoodsEffectService {

  @Effect() foods$: Observable<Action> = this.actions$
    .ofType(LOAD_FOODS_ACTION)
    .switchMap( () => this.foodService.loadServerFoods(1) ) // 1 = userID
    .map(allFoodData => new FoodsLoadedAction(allFoodData) );

  constructor(private actions$: Actions, private foodService: FoodService) {
  }
}

從效果服務調用的food-service.ts

@Injectable()
export class FoodService {

  constructor(private http: Http) { }

  loadServerFoods(userId: number): Observable<AllFoodData> {
    return this.http.get('/api/foods', commonHttpHeaders(userId)) // see proxy.config.json for the url
      .map( res => res.json() );
  }
}

serverFoodDataReducer.ts然后將http響應添加到Application State

export function serverFoodData(state: ServerFoodState = INITIAL_FOOD_DATA, action: Action): ServerFoodState {
  switch (action.type) {
    case FOODS_LOADED_ACTION:
      return handleFoodsLoadedAction(state, action);
    default:
      return state;
  }
}

export function handleFoodsLoadedAction(state: ServerFoodState, action: FoodsLoadedAction): ServerFoodState {
  return { foods: _.keyBy(action.payload.foods, 'id') };
}

同樣,一旦兩個http調用都減少到商店中,我如何觸發新操作?

在這種情況下,您將需要一個操作來觸發對服務器的兩個請求,然后觸發 3 個操作。 我認為這樣的事情應該適合你:

@Effect()
food$ = this.actions$
.ofType('LoadFood') // This one is to trigger BOTH foods, you would have 
// another action for just the SQL or Mongo data.
.switchMap(action => {
  return Observable.combineLatest(
    service.loadServerFood(),
    service.loadUserFood()
  )
}).switchMap(([serverFood, userFood]) => {
  return Observable.of(
    serverFoodLoadedAction(serverFood),
    userFoodLoadedAction(userFood),
    mergeFoodAction(serverFood, userFood)
  );
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM