Выполнение нескольких запросов Http к одной конечной точке, объединение и сортировка ответа - PullRequest
2 голосов
/ 12 марта 2019

Я пытаюсь сделать несколько запросов к API, объединить и отсортировать результат и назначить его для this.products $ observable. В основном это работает так, как теперь выглядит код (см. Ниже), так как конечный результат в итоге превращается в один список.

fetchIds () - метод получения параметров из магазина. sliceToArrays (any [], number) берет список параметров и разбивает его на более мелкие части. Причина, по которой я это делаю, состоит в том, чтобы не делать URL-адрес слишком длинным для метода GET this.api.listProducts ([], ''), поскольку URL-запрос имеет максимальный лимит символов, который срабатывает при слишком большом количестве идентификаторов. .

Проблема, с которой я сталкиваюсь, за исключением грызущего чувства, что я использую это неправильно, состоит в том, что я не могу заставить его сортировать объединенный результат; он сортирует 2 списка, прежде чем объединить их, чтобы он выглядел следующим образом [A, B, C, A, B, C] вместо [A, A, B, B, C, C].

ngOnInit() {
this.pageSize = 100;

this.products$ = this.fetchIds().pipe(
  mergeMap(ids =>
    forkJoin(this.sliceToArrays(ids, this.pageSize).map(idsList => this.api.listProducts(idsList, 'watchlist'))).pipe(
      mergeMap(products => merge(...products)),
      toArray(),
      map(products => sortBy(products, ['inventoryStatus', 'authorLastFirst']))
))); }

sliceToArrays(input: any[], maxSliceSize: number): any[][] {
const slices = Math.floor((input.length + maxSliceSize - 1) / maxSliceSize);
const collection: any[][] = [];
for (let i = 1; i <= slices; i++) {
  collection.push(input.slice((i - 1) * maxSliceSize, i * maxSliceSize));
}
return collection; }

fetchSkus() {
return this.watchListStore.items.pipe(
  filter(watchlist => watchlist !== null),
  map(watchlist => watchlist.map(i => i.id))
); }

Кто-нибудь, кто мог бы указать мне в правильном направлении? Я пробовал разные вещи в течение нескольких дней, но это (угловой, машинопись и т. Д.) На самом деле не моя область знаний.

1 Ответ

0 голосов
/ 13 марта 2019

Я не могу заставить его отсортировать объединенный результат;он сортирует 2 списка, прежде чем объединить их, чтобы он выглядел следующим образом [A, B, C, A, B, C] вместо [A, A, B, B, C, C].

Я думаю, вы можете немного сплющить поток.Также не забывайте об обработке ошибок.Может быть, что-то вроде этого:

this.products$ = this.fetchids().pipe(
  map(ids => this.sliceToArrays(ids, this.pageSize)),
  switchMap(idLists => combineLatest(...idsList.map(ids => this.api.listProducts(ids, 'watchlist')))),
  map(productLists => productLists.reduce((acc, curr) => ([...acc, ...curr]), [])),
  map(products => products.sort((a, b) => a.inventoryStatus.localCompare(b.inventoryStatus))),
  catchError(error => of([])) // and a nice message to the UI
)

Когда логика нетривиальна, как здесь, мне нравится создавать понятный человеку слой и скрывать хакерскую логику в функциях:

this.products$ = this.fetchids().pipe(
  map(ids => splitIdsIntoQueriableChunks(ids, this.pageSize)),
  switchMap(idLists => fetchAllProducts(idLists)),
  map(productLists => mergeProducts(productLists)),
  map(products => sortProducts(products)),
  catchError(error => notifyError(error))
)
...