首页 > 解决方案 > 在调用 api 之前检查对象的存储

问题描述

你知道他们怎么说你不需要状态管理,直到你知道你需要它。事实证明我的项目需要它。因此,当我将 ngxs 添加到现有的 Angular 项目中时,我需要一些最佳实践的帮助。

我有一个名为getServiceDetail的操作,我的 statemodel 有一个名为DriverListsStopInfoViewModel的对象列表。这些对象中的每一个都有一个唯一的 ID。消费组件的 html 模板使用属性currentStopDetail的选择器,这是在我的操作中设置的状态属性。

目标:

在我的操作中,我想检查商店中的对象列表,以查看是否存在具有相同 id 的对象并返回该对象,如果不存在,则调用和 api 来获取它。

例子:

以下代码有效,但我想知道这是否是正确的方法。如果找到它,我什至需要从动作函数中返回对象,还是我可以使用补丁状态将其分配给currentStopDetail

export interface SignServiceStateModel {
  searchResults: ServiceSearchModel[];
  driverStopsDetails: DriverListsStopInfoViewModel[];
  driverStopsList: DriverListsStopsViewModel[];
  driverStopsMarkers: DriverStopsMarkerViewModel[];
  currentStopDetail: DriverListsStopInfoViewModel;
}

const SIGNSERVICE_STATE_TOKEN = new StateToken<SignServiceStateModel>(
  'signservice'
);

@State<SignServiceStateModel>({
  name: SIGNSERVICE_STATE_TOKEN,
  defaults: {
    searchResults: [],
    driverStopsDetails: [],
    driverStopsList: [],
    driverStopsMarkers: [],
    currentStopDetail: null
  },
})
@Injectable()
export class SignServiceState {
  constructor(private driverListsService: DriverListsService) {}

  
  @Action(DriverList.GetServiceDetail)
  getServiceDetail(
    ctx: StateContext<SignServiceStateModel>,
    action: DriverList.GetServiceDetail
  ) {
    if (action.serviceId === undefined || action.serviceId <= 0) {
      return;
    }
    // check if record already in list and return
    const currentState = ctx.getState();
    const existingStopDetail  = currentState.driverStopsDetails.find(s => s.SignServiceId === action.serviceId);
    if (existingStopDetail  !== undefined) {
      const currentStopDetail = existingStopDetail;
      ctx.patchState({ currentStopDetail });
      return currentStopDetail;
    }
    // else get new record, add it to list and return
    return this.driverListsService.getDriverListsInfo(action.serviceId).pipe(
      tap((currentStopDetail) => {
        ctx.patchState({ currentStopDetail });
        ctx.setState(
          patch({
            driverStopsDetails: append([currentStopDetail])
          })
        );
      })
    );
  }


  @Selector()
  static currentStopDetail(state: SignServiceStateModel) {
    return state.currentStopDetail;
  }
}

我只包含了我的状态类中的相关代码

问题:

这是检查商店是否有商品并在不存在时调用 api 的最佳方法吗?

提前致谢

标签: ngxs

解决方案


简短的回答是肯定的,您在这里所做的是处理这种情况的典型方式(根据我的经验)。您可以进行一些改进:

如果找到它,我什至需要从动作函数中返回对象,还是我可以使用补丁状态将其分配给 currentStopDetail

不,您不会从这些操作处理程序返回任何内容,除了可能由ObservableNGXS 处理的(因此在您的情况下,如果没有找到匹配的项目,则返回Observable从 API 获取它并修补状态的)。

此外,当您进行 API 调用时,您应该只需要对状态进行一次更新:

return this.driverListsService.getDriverListsInfo(action.serviceId).pipe(
  tap((result) => {
    ctx.setState(
      patch({
        currentStopDetails: result
        driverStopsDetails: append([result]),
      })
    );
  })
);

推荐阅读