首页 > 解决方案 > 从效果中获取操作的有效负载类型

问题描述

有时您希望您的效果从它订阅的第一个操作中获取一个值以使用它到更高阶的可观察对象。问题是您没有这些操作有效负载的类型。

例如,我有一个包含 cityId 的 getWeather 操作,并通过 API 询问该城市的天气。这些是行动:

export const getWeather = createAction(
  '[Weather Api] Get Weather',
  props<{ cityId: number }>()
);

export const getWeatherSuccess = createAction(
  '[Weather Api] Get Weather Success',
  props<{ weather: IWeather }>()
);

这就是api调用需要使用cityId的效果:

  getWeather$ = createEffect(() => {
return this.actions$.pipe(
  ofType(WeatherApiActions.getWeather),
  switchMap((action: { type: string, cityId: number }) => this.weatherService.getWeather(action.cityId)),
  map((weather: IWeather) => WeatherApiActions.getWeatherSuccess({ weather }))
)
})

如您所见,我在效果中在这里写了类型(“cityId”)。但是这里有一个巨大的缺点,这种用法使效果与动作紧密结合。这意味着如果您决定更改“getWeather”动作,您还需要更改相应的效果。所以我认为有更好的方法来处理这个问题,我的问题是 - 如何在不破坏松耦合的情况下做到这一点

标签: angularngrx

解决方案


您可以创建一个强类型的操作,而不是使用createAction来定义您的操作:

export class GetWeather implements Action {
  readonly type = '[Weather] Get Weather';
  constructor(public cityId: number) {}
}

然后在你的效果:

  getWeather$ = createEffect(() => {
return this.actions$.pipe(
  ofType(GetWeather.type),
  switchMap((action: GetWeather => this.weatherService.getWeather(action.cityId)),
  map((weather: IWeather) => WeatherApiActions.getWeatherSuccess({ weather }))
)
})

推荐阅读