0

I am using an API that only allows 3 calls per second, and I need to make a lot of calls.

So i need to use SetTimeout with Await Axios inside a map, but i am not being able to achieve it.

I tried import setTimeout from promises, but no luck.

import { setTimeout } from 'timers/promises';

const apiCall = await Promise.all(data?.map( async item => {
  
  await setTimeout(resolve, 334)
  

  const numeroPedidoBling = item?.numeroPedidoBling;
  
  
  const orderData = await axios.get(`${BLING_URL}/${numeroPedidoBling}/json?apikey=${APIKEY}`, { headers: {
    'Accept': "application/json"
  }})


  return orderData?.data?.retorno;
}))

I tried in a lot of different ways, and now i am stuck in this piece of code.

Right now, it does not wait for the api calls and I receive erro 429 (too many calls)

How can I make it?

Obs.: 334 inside SetTimeout is 1,01 second

Edit.: I tried implementing rateLimit and for await together, but it also gives error 429, too many requests, follow the code:

try {

const result = [];

for await (let item of data) {
  const numeroPedidoBling = item?.numeroPedidoBling;

  const request = rateLimit(axios.create(), { maxRPS: 2 })
  
  
  const orderData = await request.get(`${BLING_URL}/${numeroPedidoBling}/json?apikey=${APIKEY}`, { headers: {
    'Accept': "application/json"
  }})

  result.push(orderData?.data?.retorno);
}

} catch (error) {
throw Error(error)

}

trsp
  • 78
  • 1
  • 1
  • 11
  • 2
    `.map()` is NOT promise aware at all. It does nothing with the return value from the callback you pass it other than just pass that return value back to the caller. So, when you use an `await` in the callback, your callback returns an unresolved promise and `.map()` just immediately moves right onto the next iteration, not waiting for the prior one. If you want to wait, then use a plain `for` loop which will wait its iteration for an `await`. – jfriend00 Aug 17 '22 at 05:31
  • 1
    You may be interested in [rateLimitMap()](https://stackoverflow.com/questions/36730745/choose-proper-async-method-for-batch-processing-for-max-requests-sec/36736593#36736593). – jfriend00 Aug 17 '22 at 05:38
  • I tested rateLimit alongside with map(), but no luck as well – trsp Aug 17 '22 at 14:22
  • If you want help implementing an actual rate limiting solution, then you will have to show the code you used in your question and we can look at what you're doing wrong. Rate limiting solutions like `rateLimitMap()` let you specifiy the maximum rate that requests will be sent to the target server. If you configure that rate to be below what the target server will complain about, then they will work. But, you have to implement it correctly and find out what rate will avoid the error. Just saying "it didn't work" does not allow us to help you. It will work if implemented properly. – jfriend00 Aug 17 '22 at 15:55
  • @jfriend00 added the code with rate limit and for await – trsp Aug 17 '22 at 16:14
  • What rateLimit module is that? That's not the `rateLimitMap()` that I linked to. – jfriend00 Aug 17 '22 at 16:22
  • I added a package called axios-rate-timit, but didn't work as well. I managed to make it using setTimeout inside for await. i will post the answer. thanks for the help – trsp Aug 17 '22 at 17:51

2 Answers2

0

I managed to make it by using for await, and setTimeout, as I was needind to make only 3 api calls per second, it worked.

follow the code:

import { setTimeout } from 'timers/promises';
import axios from 'axios';

const result = [];
let counter = 0;

for await (let item of data) {
  counter+=1

  const numeroPedidoBling = item?.numeroPedidoBling;

  if(counter%3 === 0) {
    await setTimeout(1000)
  }
  
  
  const orderData = await axios.get(`${BLING_URL}/${numeroPedidoBling}/json?apikey=${APIKEY}`, { headers: {
    'Accept': "application/json"
  }})

  result.push(orderData?.data?.retorno);
}
trsp
  • 78
  • 1
  • 1
  • 11