对同一端点执行多个 Http 请求,合并和排序响应
Performing multiple Http requests to same endpoint, merge and sort response
我想要实现的是向 api 发出多个请求,合并和排序结果并将其分配给 this.products$ observable。这主要是因为代码现在看起来(见下文),因为最终结果最终变成了一个列表。
fetchIds() 方法从商店获取参数。 sliceToArrays(any[], number) 接收参数列表并将其拆分为更小的部分。我这样做的原因是为了避免让 url 对于 GET 方法 this.api.listProducts([],'') 来说太长,因为 url 查询有一个最大字符限制当 ID 太多时会被击中。
我面临的问题是,除了我以错误的方式使用它的痛苦感觉之外,我无法让它对合并结果进行排序;它在组合它们之前对 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))
); }
谁能给我指出正确的方向?这几天我一直在尝试不同的东西,但这(angular、打字稿等)并不是我的专业领域。
I can't get it to sort the merged result; it sorts 2 lists, before combining them, making it look like this [A, B, C, A, B, C] instead of [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
)
当逻辑像这里一样不平凡时,我喜欢制作一个人类可读的层,并在函数中隐藏 hacky 逻辑:
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))
)
我想要实现的是向 api 发出多个请求,合并和排序结果并将其分配给 this.products$ observable。这主要是因为代码现在看起来(见下文),因为最终结果最终变成了一个列表。
fetchIds() 方法从商店获取参数。 sliceToArrays(any[], number) 接收参数列表并将其拆分为更小的部分。我这样做的原因是为了避免让 url 对于 GET 方法 this.api.listProducts([],'') 来说太长,因为 url 查询有一个最大字符限制当 ID 太多时会被击中。
我面临的问题是,除了我以错误的方式使用它的痛苦感觉之外,我无法让它对合并结果进行排序;它在组合它们之前对 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))
); }
谁能给我指出正确的方向?这几天我一直在尝试不同的东西,但这(angular、打字稿等)并不是我的专业领域。
I can't get it to sort the merged result; it sorts 2 lists, before combining them, making it look like this [A, B, C, A, B, C] instead of [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
)
当逻辑像这里一样不平凡时,我喜欢制作一个人类可读的层,并在函数中隐藏 hacky 逻辑:
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))
)