如何限制内部有异步等待 api 调用的 for in Javascript 循环?

How to throttle a for in Javascript loop that has an async await api call inside?

有没有办法限制在循环内部调用异步等待 api 的 for in Javascript 循环?这里的问题是 API 端点每个请求的速度限制为 1 秒,有些 return 错误 statusText: 'Too Many Requests',因此目标是限制循环以达到 [=每秒 20=](API return 数据在此用例中无关紧要的顺序 )。有没有办法用当前的实现来做到这一点,或者节流不适用于这个实现?

const getProductSales = async () => {
  const products = [...] // array of product slugs
  const productSales = []

  for (const product in products) {
    try {
      const response = await axios.get(
        `https://www.someapi.com/api/v1/sales/${product}`
      )
      productSales.push(
        {
          product: product,
          sales: response
        }
      )
    } catch (err) {
      console.error(err)
    }
  }

  return productSales
}

使用set timeout这可以完成。 设置超时是一个回调函数,因此等待我们可以使用 .

中的睡眠函数
const sleep = (time) => {
   return new Promise((resolve) => setTimeout(resolve, Math.ceil(time * 1000)));
};

 const getProductSales = async () => {
 const products = [...] // array of product slugs
 const productSales = []

 for (const product in products) {
    try {
      const [ response ] = await Promise.all([
          axios.get(
            `https://www.someapi.com/api/v1/sales/${product}`
          ), 
          sleep(1)
      ]);

      productSales.push(
        {
          product: product,
          sales: response
        }
      )
    } catch (err) {
      console.error(err)
    }
  }

  return productSales
}

这里我给 Promise.all() 添加了睡眠,所以请求每秒不会发生超过一次。

您可以尝试这样限制它:

...
const apiPromise = axios.get(`https://www.someapi.com/api/v1/sales/${product}`)
const throttlePromise = new Promise((res) => setTimeout(res, 1000)) //resolves after one second
const responses = await Promise.all([apiPromise, throttlePromise ])
const response = responses[0]
...

Promise.all() 将采用一系列承诺,并在所有承诺都解决后解决一系列结果。因此,如果 api 请求花费的时间少于一秒,它将在继续循环之前等待该 throttlePromise。