Javascript delay/wait/sleep

Hello guys, new to retool and the community... Sorry for this novice question. Should be an easy hitter I imagine.
We are attempting to us JS to loop through some data and fire off some API calls. However, we are hitting an API rate limit issue. We are limited to 4 calls per second. My initial thought was to add a Utilities.sleep(1000); line inside my loop to slow it down to 1 API request being triggered every 1 second. I don't believe the utilities function works in retool. We have been pursuing utils method, setTimeout function, LoDash (_.delay), etc. but so far everything just fires off the API calls without delay. Perhaps I am writing this incorrectly.
Can anybody enlighten me on how to properly delay within retool?
Thanks,
Jonathan

Javascript is inherently asynchronous, so depending on how you’re making the API calls, they should usually kick off immediately (essentially in parallel), unless you use a Promise or async/await notations to do them synchronously. Here is an article explaining the difference: https://jrsinclair.com/articles/2019/how-to-run-async-js-in-parallel-or-sequential/ Do you have a code snippet of your loop?

awesome Patrick, thanks for the quick reply. I will look into this article that you sent. Below is the code I am using (at least one iteration of it - I have tried many different variations!)

var variant_ids = [17651552878682,17651554680922,17670906249306,17668986732634,17891973202010,{...break here just for brevity's sake...} ,17644602720346]; 
function func() {
PriceChange.trigger(
{
additionalScope:
{
variant_id : variant_id
}
}
)};
//var variantid = pricechange_variantid.value;
for (i = 0; i < variant_ids.length; i++)
{
var variant_id = variant_ids[i];
setTimeout(func(), 1000);
}

I haven't tested this, so it probably won't work out of the box, but I think this is the kind of thing you should be looking at:

async function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function makeRequests(variant_ids) {
  for (i = 0; i < variant_ids.length; i++) {
    await delay(1000)
    await PriceChange.trigger({
      additionalScope: {
        variant_id: variant_ids[i],
      },
    })
  }
}
1 Like

Hey Patrick, thanks for the point in the correct direction. The article you sent was informative, but then lost me at the code (however, I now understand the concept!)... and your suggested code got me thinking in the right direction!
I ended up using the following code to loop through my array and make a single API call with 1 second in between each call:

var variant\_ids = pricechange\_variantid.value; //array of values to be used one at a time in an API call

loop();

async function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function makeRequests(variant\_id) {
await PriceChange.trigger({
additionalScope: {
variant\_id: variant\_id,
},
}
)
}
async function loop() {
for (i = 0; i < variant\_ids.length; i++) {
  var variant_id = variant_ids[i];
await delay(1000)

makeRequests(variant\_id);
}
}

Thanks for the help - I hope this helps others in the future as well! My way may not be the prettiest way, but it worked!

Awesome. Quick modernisation:

const delay = async ms => new Promise(resolve => setTimeout(resolve, ms))

const loop2 = async () => pricechange_variantid.value
  .map(async variant_id => {
    await delay(1000)
    PriceChange.trigger({
      additionalScope: { variant_id }
    })
  })

loop2()
1 Like