проверить магазин на предмет перед вызовом API - PullRequest
0 голосов
/ 25 апреля 2020

Вы знаете, как они говорят, что вам не нужно государственное управление, пока вы не знаете, что оно вам нужно. Хорошо получается, что мой проект нуждается в этом. Поэтому мне нужна помощь с наилучшей практикой, так как я добавляю ngxs в существующий проект angular.

У меня есть действие с именем getServiceDetail , и моя модель состояния имеет список объектов с именем DriverListsStopInfoViewModel . каждый из этих объектов имеет уникальный идентификатор. Шаблон html компонента потребления использует селектор для свойства currentStopDetail , которое является свойством состояния, которое устанавливается в моем действии.

GOAL:

in мое действие Я хочу проверить список объектов в моем магазине, чтобы увидеть, существует ли объект с таким же идентификатором, и вернуть этот объект, а если он не существует, вызвать и 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, если он не существует?

Заранее спасибо

1 Ответ

1 голос
/ 27 апреля 2020

Короткий ответ - да, то, что вы сделали здесь, является типичным способом справиться с этим сценарием (по моему опыту). Есть пара улучшений, которые вы можете сделать:

нужно ли мне вообще возвращать объект из функции действия, если он найден, или я могу просто использовать состояние патча, чтобы назначить его для currentStopDetail

Нет, вы не возвращаете ничего из этих обработчиков действий, кроме, возможно, Observable, который будет обрабатывать NGXS (так что в вашем случае, если не найден соответствующий элемент, вы возвращаете Observable, который извлекает его из API и исправляет состояние).

Также, когда вы делаете вызов API, вам нужно только одно обновление состояния:

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