Search code examples
javascriptasynchronousgoogle-apirate-limiting

Rate Limit: Add a buffer beween API calls in map JavaScript


I'm using Google Gmail API to get sent emails.

I'm using 2 APIs for this -

The list API gives a list of messages IDs which I use to get specific data from the get API.

Here's the code for this -

await Promise.all(
            messages?.map(async (message) => {
                const messageData = await contacts.getSentGmailData(
                    accessToken,
                    message.id
                );
                return messageData;
            })
        );

getSentGmailData is the get API here.

The problem here is, while mapping and making requests to this API continuously, I get a 429 (rateLimitExceeded) error.

What I tried is adding a buffer between each request like this -

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


const messageData = await contacts.getSentGmailData(accessToken,message.id);
await delay(200);

But this doesn't seem to work.

How can I work around this?


Solution

  • The reason the delay is not working is because it does not wait for the Promise to be resolved. The same reasoning applied to forEach, filter, reduce etc. You can get some idea here: https://gist.github.com/joeytwiddle/37d2085425c049629b80956d3c618971

    If you had used a for-of loop or another for-loop for this purpose, it would have worked.

    for(let message of messages) {
     const messageData = await contacts.getSentGmailData(accessToken,message.id);
     await delay(200);
    }
    

    You could also write your own rate-limiting function (also commonly called throttling function) or use one provided by libraries like Lodash: https://lodash.com/docs#throttle