Adding timeout delay to a loop

Viewed 65

I'm in a need to update a firestore collection where each document requires an external API call. The API I'm using has a limit of 1 request per 10ms so without exceeding the quota limits Im trying to update my collections of 100's of elements

async function timeout(ms:number) {
return new Promise(resolve => setTimeout(resolve, ms)); 
}

async function update(): Promise<void>{
const requests : bird<void>[] = [] 
const charts = await db.collection("charts5D").get()
charts.forEach(async(doc)=>{
    await timeout(1000).then(async()=>{
        // code that does a network request
        const request = req(options).then(async(response)=>{} 
        requests.push(request)
        
    })
})
return Promise.all(requests).then(()=>{
    console.log("kk")
}).catch((error)=>{
    console.log(error)
})} 

I added an artificially long delay of 1s to make sure the delays are working, however it seems that only the first time the loop runs the timeout is working, after that it still fires out the requests without any delay in effect and I get a Too Many Requests response from the api. I tried simply doing await timeout(1000) and just adding the request code below but that still doesn't work

1 Answers

The setTimeout functions adds a timer to your browser and executes the code inside after the specified milliseconds have passed.

The problem here is that you are calling setTimeout(1000) on all of them, without any delay between. The delay only starts counting AFTER the setTimeout function is called. So after 1 second, all your timers are up and they all resolve.

To fix this, pass the index of your chart into the timeout function parameter, like this:

charts.forEach(async(doc, index)=>{
   await timeout(index*1000).then(async()=>{
      // code that does a network request
      const request = req(options).then(async(response)=>{} 
      requests.push(request)       
   })
})

So the first timer will be up in 1 second, the second timer in 2 seconds, etc.

Related