对同一个端点执行多个Http请求,合并和排序响应

时间:2019-03-12 14:10:23

标签: angular typescript rxjs angular6 angular-httpclient

我想要实现的是对一个api发出多个请求,合并并排序结果,然后将其分配给this.products $ observable。多数情况下,这就像现在的代码一样(参见下文),因为最终结果最终变成了一个列表。

fetchIds()方法从商店获取参数。 sliceToArrays(any [],number)进入参数列表并将其拆分为较小的部分。我这样做的原因是为了避免GET方法this.api.listProducts([],'')的网址过长,因为url查询的最大字符数限制是当ID过多时会被点击

我所面临的问题,除了the不安的是我使用这种错误方法的感觉之外,是我无法获取它来对合并结果进行排序;它会对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 :(得分:0)

  

我无法对合并结果进行排序;它会对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))
)