简体   繁体   English

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

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

Is there a way to throttle a for in Javascript loop that has an async await api call inside of the loop?有没有办法限制循环内部有异步等待 api 调用for in The problem here is that the API endpoint has a speed throttle of 1 second per request and some return with the error statusText: 'Too Many Requests' , so the goal is to throttle the loop to hit the API every second ( the order that the API returns the data is not of concern in this use case ).这里的问题是 API 端点的每个请求的速度限制为 1 秒,并且有些返回错误statusText: 'Too Many Requests' ,因此目标是限制循环每秒命中 API( API 返回的数据在这个用例中并不重要)。 Is there a way to do this with the current implementation or does throttling not work with this implementation?有没有办法用当前的实现来做到这一点,或者节流不适用于这个实现?

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
}

Using set timeout this can be accomplished.使用set timeout这可以完成。 Set timeout is a callback function so to await we can use this sleep function from https://stackoverflow.com/a/72408587/10772577 .设置超时是一个回调函数,所以等待我们可以使用https://stackoverflow.com/a/72408587/10772577中的这个睡眠函数。

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
}

Here I have added sleep to a Promise.all() so the request should not happen more than once per second.在这里,我在Promise.all()中添加了睡眠,因此请求每秒发生的次数不应超过一次。

You could try throttling it like that:您可以尝试像这样限制它:

...
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() will take an array of promises and resolve an array of results when all of them are resolved. Promise.all()将接受一组承诺并在所有结果都解决后解决一组结果。 So if the api request takes shorter than one second, it will wait for that throttlePromise before continuing the loop.因此,如果 api 请求的时间短于一秒,它将在继续循环之前等待该 throttlePromise。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM