如何完成2个http请求,然后触发另一个Action来合并结果

时间:2017-01-26 03:45:21

标签: http angular typescript ngrx

我有相同的数据类型存储在2个不同的数据库中。

  • SQL数据库中,我存储了大量的所有食物。
  • Mongo数据库上,我正在存储个人的食物数据 覆盖提供的默认食物数据。

这两种类型的数据都将存储在我的ngrx商店应用程序状态以及合并状态中。

export interface ApplicationState {
   allSQLFoodData: FoodData;
   allUserFoodData: FoodData;
   mergedFoodData: FoodData;
}

我需要做的是从后端获取allSQLFoodDataallUserFoodData,将这些值存储到状态,并合并合并状态下的两组数据。

我通过dispatch()动作INITIALIZE_DATA_ACTION来执行此操作,然后我在效果服务中进行操作。

这是我在效果服务中所处的位置:

初始化数据效果的service.ts

@Injectable()
export class InitializeDataEffectService {

   @Effect() initialize$: Observable<Action> = this.actions$
     .ofType(INITIALIZE_DATA_ACTION)
     .switchMap( (action) => {
      return Observable.combineLatest(
        this.foodService.loadSQLFoods( action.payload ),
        this.userDataService.loadUserData( action.payload )
      )
    })
    .switchMap(([allSQLFoodData, allUserData]) => {
      return Observable.of(
        new SQLFoodsLoadedAction( allSQLFoodData ),
        new UserDataLoadedAction( allUserData ),
        new BuildMergedFoodDataAction({sql: allSQLFoodData, user: allUserData})
      )
    })

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

  }
}

正如您所看到的,我正在侦听INITIALIZE_DATA_ACTION类型的操作,并使用combineLatest()响应中的http创建组合的可观察对象。然后我调用Action类来为每个类设置Application状态:

.switchMap(([allSQLFoodData, allUserData]) => {
  return Observable.of(
    new SQLFoodsLoadedAction( allSQLFoodData ),
    new UserDataLoadedAction( allUserData ),
    new BuildMergedFoodDataAction({sql: allSQLFoodData, user: allUserData})
  )
})

但这会产生以下错误:

  

类型参数的类型参数&#39; T&#39;无法从中推断出来   用法。考虑明确指定类型参数。类型   论证候选人&#39; SQLFoodsLoadedAction&#39;不是有效的类型参数   因为它不是候选人的超类型&#39; UserDataLoadedAction&#39;。       财产类型&#39;有效载荷&#39;是不相容的。         输入&#39; AllUserData&#39;不能分配类型&#39; AllSQLFoodData&#39;。           物业&#39;食物&#39;类型&#39; AllUserData&#39;。

中缺少

我不确定如何

  

明确指定类型参数

即使我这样做了,我也不确定Effect()装饰器现在如何将结果分配给适当的状态值。 我该如何实现?

1 个答案:

答案 0 :(得分:3)

要从效果中发出多个动作的switchMap返回一个observable,请使用Observable.from,它可以采用数组:

import 'rxjs/add/observable/from';
import 'rxjs/add/operator/concatMap';

...
.concatMap(([allSQLFoodData, allUserData]) => Observable.from([
  new SQLFoodsLoadedAction( allSQLFoodData ),
  new UserDataLoadedAction( allUserData ),
  new BuildMergedFoodDataAction({sql: allSQLFoodData, user: allUserData})
]))

请注意,switchMap是不必要的,因为返回的observable会立即发出。您可以改为使用concatMap

此外,效果不会为州分配任何东西。它唯一的作用是发出行动。这些操作将由缩减器处理,缩减器将更新应用程序状态的适当部分。