首页 > 解决方案 > Javascript | 使用 promise.all 将请求拆分成块

问题描述

我们正在尝试将请求拆分为多个块,因为外部 API 对我们每页可以显示的产品数量有限制。

假设我们总共有 113 个产品,但每页仅显示 5 个,这些产品是通过将产品 ID 作为参数 ( productIds[]=x&productIds[]=y) 传递来获取的。我们知道总共有 113 个,限制为 5 个,但是,我们不想通过等待前一个请求完成来减慢速度,所以我们想使用Promise.all().

我知道我可以使用slice它,但是,我希望我能够将它映射到一个数组中。

所以我们有一个起始数组,就像

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...]

这些都是产品 ID,然后我们需要为每 5 个引用这些 ID 的产品发送一个请求。

await axios.get('http://external.api/product', { params: { productIds: productIds.slice(0, 5) } }

但是,我想做类似以下的事情:

Promise.all(
  productIds.map(
    product => axios.get('...', { params: {productIds: (subset of 5 products in chunks )}
  )
)

标签: javascriptpromise

解决方案


我会使用两个函数来实现这一点。chunkpromiseAllordelaychunk.

这是我用来按计数对列表进行分组的块函数。

const chunk = <T>(arr: T[], size: number): T[][] => [
  ...Array(Math.ceil(arr.length / size)),
].map((_, i) => arr.slice(size * i, size + size * i));

并带有 Promise 的延迟功能。

const delay = (ms: number) => {
  return new Promise<void>((resolve) => setTimeout(resolve, ms));
}

如果 API 在时间上没有任何限制,您可以使用它:

const groupedIdList = chunk(idList, PAGESIZE);
const result = await Promise.all(groupedIdList.map(idList) => myFetchFunctionPromise(idList));
const data = result.flat();

如果 API 有一些限制,您需要延迟您的请求。

  const data = await groupedIdList.reduce(async (prev, subIdList) => {
    const result = await prev;
    const newDataList = await myFetchFunctionPromise(subIdList);
    // wait some time ms
    await delay(500);
    return [...result, ...newDataList];
  }, Promise.resolve([]));

推荐阅读